【bzoj1212】[HNOI2004]L语言 AC自动机
題目描述
標點符號的出現晚于文字的出現,所以以前的語言都是沒有標點的。現在你要處理的就是一段沒有標點的文章。 一段文章T是由若干小寫字母構成。一個單詞W也是由若干小寫字母構成。一個字典D是若干個單詞的集合。 我們稱一段文章T在某個字典D下是可以被理解的,是指如果文章T可以被分成若干部分,且每一個部分都是字典D中的單詞。 例如字典D中包括單詞{‘is’, ‘name’, ‘what’, ‘your’},則文章‘whatisyourname’是在字典D下可以被理解的 因為它可以分成4個單詞:‘what’, ‘is’, ‘your’, ‘name’,且每個單詞都屬于字典D,而文章‘whatisyouname’ 在字典D下不能被理解,但可以在字典D’=D+{‘you’}下被理解。這段文章的一個前綴‘whatis’,也可以在字典D下被理解 而且是在字典D下能夠被理解的最長的前綴。 給定一個字典D,你的程序需要判斷若干段文章在字典D下是否能夠被理解。 并給出其在字典D下能夠被理解的最長前綴的位置。
輸入
輸入文件第一行是兩個正整數n和m,表示字典D中有n個單詞,且有m段文章需要被處理。 之后的n行每行描述一個單詞,再之后的m行每行描述一段文章。 其中1<=n, m<=20,每個單詞長度不超過10,每段文章長度不超過1M。
輸出
對于輸入的每一段文章,你需要輸出這段文章在字典D可以被理解的最長前綴的位置。
樣例輸入
4 3
is
name
what
your
whatisyourname
whatisyouname
whaisyourname
樣例輸出
14
6
0
題解
水題
因為單詞可能有包含關系,所以不能貪心來做。
由于題目中數據范圍很小,可以考慮用動態規劃。
f[i]表示能否理解前i個單詞
把后面的字符放到Trie樹中,直至沒有對應子節點。
如果遇到單詞,那么修改狀態,f[j]|=f[i]。
最后掃一遍輸出答案。
#include <cstdio> #include <cstring> #include <queue> using namespace std; queue<int> q; int nt[201][26] , cnt[201] , tot = 1; bool f[1000001]; char str[1000001]; int main() {int n , m , i , j , l , t , ans;scanf("%d%d" , &n , &m);while(n -- ){scanf("%s" , str);l = strlen(str);t = 1;for(i = 0 ; i < l ; i ++ ){if(!nt[t][str[i] - 'a'])nt[t][str[i] - 'a'] = ++tot;t = nt[t][str[i] - 'a'];}cnt[t] ++ ;}while(m -- ){scanf("%s" , str);l = strlen(str);memset(f , 0 , sizeof(f));f[0] = 1;for(i = 0 ; i < l ; i ++ ){if(f[i]){t = 1;j = i;while(nt[t][str[j] - 'a']){t = nt[t][str[j ++ ] - 'a'];if(cnt[t]) f[j] |= f[i];}} }for(i = 0 ; i <= l ; i ++ )if(f[i])ans = i;printf("%d\n" , ans);}return 0; }轉載于:https://www.cnblogs.com/GXZlegend/p/6264966.html
總結
以上是生活随笔為你收集整理的【bzoj1212】[HNOI2004]L语言 AC自动机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原: 安装VMtools过程流水帐
- 下一篇: OOP的字段