3.3 字符串(1)

Trie 前綴樹 字典樹  node

例題11  LA 3942 http://acm.hust.edu.cn/vjudge/problem/22109c++

字典樹第一個例題我用set水過,先記錄這個版本吧,題意是,給一個串,還有一些短串的集合,問有多少種不一樣的拆分方法使得拆分完後,每一個子串都在集合中。數組

dp[len] 表示前len個有多少拆分法 dp[0]=1, 前0個字符有一種拆分法,空嘛。  dp[len] 就是答案,  轉移就是, 若是接下來一段在集合中,那麼就能夠轉移到長度加這段的長度。ide

 

起點有la=3e5,,對每個起點,加的串可能有lbi=100,都要枚舉,接下來就是判斷這個串是否存在,用hash值判,o1,set查詢logn ,n=4000, 整體複雜度 la*lb*logn 飄過2700ms。spa

 

 1 //#define txtout
 2 //#define debug
 3 #include<bits/stdc++.h>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 typedef long long LL;
 7 const double pi=acos(-1.0);
 8 const double eps=1e-8;
 9 const int inf=0x3f3f3f3f;
10 const int M=3e5+10;
11 const LL MOD=20071027;
12 class String_Hash {///字符串哈希 init O(n) query O(1)
13     typedef unsigned long long typec;///hash 值類型
14     static const int MV=3e5+10;///串長度
15     static const int key=137;///hash 種子值選素數好
16     typec H[MV],xp[MV];
17 public:
18     void init(char s[],int ls) { ///傳入串數組和串長
19         H[ls]=0;
20         for(int i=ls-1; i>=0; i--) {
21             H[i]=H[i+1]*key+s[i];
22         }
23         xp[0]=1;
24         for(int i=1; i<=ls; i++) {
25             xp[i]=xp[i-1]*key;
26         }
27     }
28     typec get(int pos,int len) { ///傳入初始位置 pos,串長 len,返回串 hash 值
29         return H[pos]-H[pos+len]*xp[len];
30     }
31 }Hash;
32 int n;
33 char a[M];
34 char b[4010][110];
35 LL dp[M];
36 set<unsigned long long> s;
37 int max_len;
38 void init_set() {
39     s.clear();
40     max_len=0;
41     for(int i=0; i<n; i++) {
42         int lb=strlen(b[i]);
43         Hash.init(b[i],lb);
44         s.insert(Hash.get(0,lb));
45         max_len=max(max_len,lb);
46     }
47 }
48 LL solve() {
49     init_set();
50     int len=strlen(a);
51     for(int i=0; i<=len; i++) {
52         dp[i]=0;
53     }
54     dp[0]=1;
55     Hash.init(a,strlen(a));
56     for(int i=0; i<len; i++) {
57         if(dp[i]==0) continue;
58         for(int j=0; j<max_len; j++) {
59             if(!s.count(Hash.get(i,j+1))) continue;
60             dp[i+j+1]+=dp[i];
61             dp[i+j+1]%=MOD;
62         }
63     }
64     return dp[len];
65 }
66 int main() {
67 #ifdef txtout
68     freopen("in.txt","r",stdin);
69     freopen("out.txt","w",stdout);
70 #endif // txtout
71     int cas=1;
72     while(~scanf("%s%d",a,&n)) {
73         for(int i=0; i<n; i++) {
74             scanf("%s",b[i]);
75         }
76         printf("Case %d: %lld\n",cas++,solve());
77     }
78     return 0;
79 }
View Code

 

 字典樹特別快72ms.  與上一種方法的差異就在於,用字典樹存小串集合,而後仍是枚舉起點, 更新的時候就在字典樹裏更新, 遇到一個串就更新一個dp, 最壞狀況複雜度 la*lb.debug

 

  1 //#define txtout
  2 //#define debug
  3 #include<bits/stdc++.h>
  4 #define mt(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 typedef long long LL;
  7 const double pi=acos(-1.0);
  8 const double eps=1e-8;
  9 const int inf=0x3f3f3f3f;
 10 const int M=3e5+10;
 11 const LL MOD=20071027;
 12 class Trie_tree {   //字典樹  前綴樹
 13     struct node {
 14         int next[26],ptr,num;// ptr在字典中的位置,num此結點出現幾回,
 15         void init() {
 16             ptr=-1;
 17             num=0;
 18             mt(next,0);
 19         }
 20     } s[M];
 21     int ls,p;
 22     int f(char c) {
 23         return c-'a';
 24     }
 25 public:
 26     void init() {
 27         s[1].init();
 28         p=0;
 29         ls=2;
 30     }
 31     void Insert(char ch[]) {
 32         int head=1;
 33         for(int k=0; ch[k]; k++) {
 34             int id=f(ch[k]);
 35             if(!s[head].next[id]) {
 36                 s[head].next[id]=ls;
 37                 s[ls++].init();
 38             }
 39             head=s[head].next[id];
 40             s[head].num++;
 41         }
 42         s[head].ptr=p++;
 43     }
 44     int query(char ch[],int op) {
 45         int head=1;
 46         for(int k=0; ch[k]&&head; k++) {
 47             head=s[head].next[f(ch[k])];
 48         }
 49         if(op) { //op==1 查ptr
 50             if(head) return s[head].ptr;
 51             return -1;
 52         } else { //op==0 查num
 53             if(head) return s[head].num;
 54             return 0;
 55         }
 56     }
 57     void solve(int i,char ch[],LL dp[]){
 58         int head=1;
 59         for(int k=i;ch[k]&&head;k++){
 60             int id=f(ch[k]);
 61             if(!s[head].next[id]) return ;
 62             head=s[head].next[id];
 63             if(s[head].ptr!=-1){
 64                 dp[k+1]+=dp[i];
 65                 dp[k+1]%=MOD;
 66             }
 67         }
 68     }
 69 } trie;
 70 int n;
 71 char a[M];
 72 char b[4010][110];
 73 LL dp[M];
 74 void init_trie() {
 75     trie.init();
 76     for(int i=0; i<n; i++) {
 77         trie.Insert(b[i]);
 78     }
 79 }
 80 LL solve() {
 81     init_trie();
 82     int len=strlen(a);
 83     for(int i=0; i<=len; i++) {
 84         dp[i]=0;
 85     }
 86     dp[0]=1;
 87     for(int i=0; i<len; i++) {
 88         if(dp[i]==0) continue;
 89         trie.solve(i,a,dp);
 90     }
 91     return dp[len];
 92 }
 93 int main() {
 94 #ifdef txtout
 95     freopen("in.txt","r",stdin);
 96     freopen("out.txt","w",stdout);
 97 #endif // txtout
 98     int cas=1;
 99     while(~scanf("%s%d",a,&n)) {
100         for(int i=0; i<n; i++) {
101             scanf("%s",b[i]);
102         }
103         printf("Case %d: %lld\n",cas++,solve());
104     }
105     return 0;
106 }
View Code

 

 

例題12 uva 11732 http://acm.hust.edu.cn/vjudge/problem/284383d

題意, 給n個字符串,用題目中的strcmp兩兩比較,須要執行多少次==判斷.code

暴力n2枚舉, 最壞len計算次數.超時.blog

字典樹作法,先把全部串插入字典樹, 而後枚舉一個串去字典樹中查詢, 對於串的每一位,都須要和全部串執行一次==,經過字典樹節點記錄的次數能夠o1累加, 而後和該位置相等的串會多執行一次=='\0',也能夠o1獲得.字符串

由於\0也會比較一次,而字典樹中我沒存,因此我在每一個串後面加個#表示\0,這樣比較時不須要特判他了.  而後每一個串會多算一個和本身的次數,  扣去2倍的長度便可,由於和本身老是能比較到最後一位.  每一對會算兩次,最後答案除2便可.

 

  1 //#define txtout
  2 //#define debug
  3 #include<bits/stdc++.h>
  4 #define mt(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 typedef long long LL;
  7 const double pi=acos(-1.0);
  8 const double eps=1e-8;
  9 const int inf=0x3f3f3f3f;
 10 const int M=4e3+10;
 11 class Trie_tree {   //字典樹  前綴樹
 12     struct node {
 13         int next[63],ptr,num;// ptr在字典中的位置,num此結點出現幾回,
 14         void init() {
 15             ptr=-1;
 16             num=0;
 17             mt(next,0);
 18         }
 19     } s[M*1000];
 20     int ls,p;
 21     int f(char c) {
 22         if(c>='a'&&c<='z') return c-'a';
 23         if(c>='A'&&c<='Z') return c-'A'+26;
 24         if(c>='0'&&c<='9') return c-'0'+52;
 25         return 62;
 26     }
 27 public:
 28     void init() {
 29         s[1].init();
 30         p=0;
 31         ls=2;
 32     }
 33     void Insert(char ch[]) {
 34         int head=1;
 35         for(int k=0; ch[k]; k++) {
 36             int id=f(ch[k]);
 37             if(!s[head].next[id]) {
 38                 s[head].next[id]=ls;
 39                 s[ls++].init();
 40             }
 41             head=s[head].next[id];
 42             s[head].num++;
 43         }
 44         s[head].ptr=p++;
 45     }
 46     int query(char ch[],int op) {
 47         int head=1;
 48         for(int k=0; ch[k]&&head; k++) {
 49             head=s[head].next[f(ch[k])];
 50         }
 51         if(op) { //op==1 查ptr
 52             if(head) return s[head].ptr;
 53             return -1;
 54         } else { //op==0 查num
 55             if(head) return s[head].num;
 56             return 0;
 57         }
 58     }
 59     LL solve(char ch[]){
 60         LL sum=0;
 61         int head=1;
 62         LL presum=-1;
 63         for(int k=0; ch[k]&&head; k++) {
 64             if(presum==-1){
 65                 presum=0;
 66                 for(int i=0;i<63;i++){
 67                     int next=s[head].next[i];
 68                     if(!next) continue;
 69                     presum+=s[next].num;
 70                 }
 71             }
 72             sum+=presum;
 73             head=s[head].next[f(ch[k])];
 74             sum+=s[head].num;
 75             presum=s[head].num;
 76         }
 77         return sum;
 78     }
 79 } trie;
 80 int n;
 81 char a[M][M];
 82 LL solve(){
 83     trie.init();
 84     for(int i=0;i<n;i++){
 85         strcat(a[i],"#");
 86         trie.Insert(a[i]);
 87     }
 88     LL sum=0;
 89     for(int i=0;i<n;i++){
 90         sum+=trie.solve(a[i]);
 91         sum-=strlen(a[i])*2;
 92     }
 93     return sum/2;
 94 }
 95 int main(){
 96     #ifdef txtout
 97     freopen("in.txt","r",stdin);
 98     freopen("out.txt","w",stdout);
 99     #endif // txtout
100     int cas=1;
101     while(~scanf("%d",&n),n){
102         for(int i=0;i<n;i++){
103             scanf("%s",a[i]);
104         }
105         printf("Case %d: %lld\n",cas++,solve());
106     }
107     return 0;
108 }
View Code

 

 

 例題13 la 3026 http://acm.hust.edu.cn/vjudge/problem/29342

kmp例題, 又拿hash水過了, 發現hash雖然理論上有機率衝突,有機率出錯, 可是實際使用起來, 很好.  

這題對每個前綴,想知道該前綴最多能分紅幾塊, 使得每一塊都相等, 若是塊數大於1,就輸出.

hash解法, 枚舉一個前綴, 而後枚舉該前綴日後能有多少段相等, 每找到一個相等, 就能更新一次. 複雜度 n *( 1/1 + 1/2 + 1/n) 調和級數 並不大。 好像ln n吧? 

 

 1 //#define txtout
 2 //#define debug
 3 #include<bits/stdc++.h>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 typedef long long LL;
 7 const double pi=acos(-1.0);
 8 const double eps=1e-8;
 9 const int inf=0x3f3f3f3f;
10 const int M=1e6+10;
11 class String_Hash {///字符串哈希 init O(n) query O(1)
12     typedef unsigned long long typec;///hash 值類型
13     static const int MV=1e6+10;///串長度
14     static const int key=137;///hash 種子值選素數好
15     typec H[MV],xp[MV];
16 public:
17     void init(char s[],int ls) { ///傳入串數組和串長
18         H[ls]=0;
19         for(int i=ls-1; i>=0; i--) {
20             H[i]=H[i+1]*key+s[i];
21         }
22         xp[0]=1;
23         for(int i=1; i<=ls; i++) {
24             xp[i]=xp[i-1]*key;
25         }
26     } typec get(int pos,int len) { ///傳入初始位置 pos,串長 len,返回串 hash 值
27         return H[pos]-H[pos+len]*xp[len];
28     }
29 } gx;
30 int n;
31 char a[M];
32 int b[M];
33 typedef pair<int,int> pii;
34 vector<pii> answer;
35 void init() {
36     int la=strlen(a);
37     for(int i=0; i<la; i++) {
38         b[i]=1;
39     }
40     gx.init(a,la);
41 }
42 void solve() {
43     init();
44     int la=strlen(a);
45     for(int i=0;i<la;i++){
46         int len=i+1;
47         for(int j=i+1;j+len-1<la;j+=len){
48             if(gx.get(0,len)!=gx.get(j,len)) break;
49             b[j+len-1]=max(b[j+len-1],(j+len)/len);
50         }
51     }
52     answer.clear();
53     for(int i=0;i<la;i++){
54         if(b[i]>1){
55             answer.push_back(make_pair(i+1,b[i]));
56         }
57     }
58 }
59 int main() {
60 #ifdef txtout
61     freopen("in.txt","r",stdin);
62     freopen("out.txt","w",stdout);
63 #endif // txtout
64     int cas=1;
65     while(~scanf("%d",&n),n) {
66         scanf("%s",a);
67         solve();
68         printf("Test case #%d\n",cas++);
69         for(int i=0; i<answer.size(); i++) {
70             printf("%d %d\n",answer[i].first,answer[i].second);
71         }
72         puts("");
73     }
74     return 0;
75 }
View Code

 

 白書kmp不是很容易理解 ,  先記錄一下吧.

 1 //#define txtout
 2 //#define debug
 3 #include<bits/stdc++.h>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 typedef long long LL;
 7 const double pi=acos(-1.0);
 8 const double eps=1e-8;
 9 const int inf=0x3f3f3f3f;
10 const int M=1e6+10;
11 int n;
12 char a[M];
13 int f[M];
14 typedef pair<int,int> pii;
15 vector<pii> answer;
16 void getFail(char* P,int* f){
17     int m=strlen(P);
18     f[0]=0;
19     f[1]=0;
20     for(int i=1;i<m;i++){
21         int j=f[i];
22         while(j&&P[i]!=P[j]) j=f[j];
23         f[i+1]=P[i]==P[j]?j+1:0;
24     }
25 }
26 void solve() {
27     getFail(a,f);
28     answer.clear();
29     int la=strlen(a);
30     for(int i=0;i<=la;i++){
31         if(f[i]>0&&i%(i-f[i])==0){
32             answer.push_back(make_pair(i,i/(i-f[i])));
33         }
34     }
35 }
36 int main() {
37 #ifdef txtout
38     freopen("in.txt","r",stdin);
39     freopen("out.txt","w",stdout);
40 #endif // txtout
41     int cas=1;
42     while(~scanf("%d",&n),n) {
43         scanf("%s",a);
44         solve();
45         printf("Test case #%d\n",cas++);
46         for(int i=0; i<answer.size(); i++) {
47             printf("%d %d\n",answer[i].first,answer[i].second);
48         }
49         puts("");
50     }
51     return 0;
52 }
View Code

 

 

例題14 la 4670 http://acm.hust.edu.cn/vjudge/problem/19224

ac自動機例題 不會, 可是kmp能夠水過.  求出現次數最多的子串. 暴力一個個kmp看出現次數.

 1 //#define txtout
 2 //#define debug
 3 #include<bits/stdc++.h>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 typedef long long LL;
 7 const double pi=acos(-1.0);
 8 const double eps=1e-8;
 9 const int inf=0x3f3f3f3f;
10 const int M=1e6+10;
11 class KMP { ///模式匹配(kmp)O(ls+lp)
12     typedef char typec;///文本元素的類型
13     static const int MV=1e6+10;///字符串的長度
14     int next[MV];
15 public:///匹配串長度 ls,str 存待匹配文本,模式串長度 lp,pat 存模式串
16     int kmp(int ls,typec str[],int lp,typec pat[],int res[]) { ///返回匹配次數,res 中存儲每一個匹配的初始位置
17         int i=0,j=-1,cnt=0;
18         next[0]=-1;
19         while(i<lp) {
20             if(j==-1||pat[i]==pat[j]) {
21                 next[++i]=++j;
22                 continue;
23             }
24             j=next[j];
25         }
26         i=j=0;
27         while(i<ls) {
28             while(j!=lp&&str[i]==pat[j]) {
29                 i++;
30                 j++;
31             }
32             if(!j) {
33                 i++;
34                 continue;
35             }
36             if(j==lp) {
37                 res[cnt++]=i-j;
38             }
39             j=next[j];
40         }
41         return cnt;
42     }
43 } gx;
44 int n;
45 struct Q{
46     char a[128];
47     int time;
48 }q[210];
49 char b[M];
50 int res[M];
51 int answer;
52 void solve(){
53     answer=0;
54     int lb=strlen(b);
55     for(int i=0;i<n;i++){
56         q[i].time=gx.kmp(lb,b,strlen(q[i].a),q[i].a,res);
57         answer=max(answer,q[i].time);
58     }
59 }
60 int main() {
61 #ifdef txtout
62     freopen("in.txt","r",stdin);
63     freopen("out.txt","w",stdout);
64 #endif // txtout
65     while(~scanf("%d",&n),n) {
66         for(int i=0; i<n; i++) {
67             scanf("%s",q[i].a);
68         }
69         scanf("%s",b);
70         solve();
71         printf("%d\n",answer);
72         for(int i=0;i<n;i++){
73             if(q[i].time==answer){
74                 puts(q[i].a);
75             }
76         }
77     }
78     return 0;
79 }
View Code

ac自動機代碼 need to write.

 

 

 例題15 uva 11468 

ac自動機  need to write.

 

例題16  uva 11019

 

暴力kmp加bitset 水過.  求一個字符矩陣在一個大字符矩陣出現幾回.  枚舉每一行, bitset每一位 1 表示該位爲起點匹配上了, x行與運算, 1的個數就是矩陣匹配次數, 中間也能夠break 剪枝.

  1 //#define txtout
  2 //#define debug
  3 #include<bits/stdc++.h>
  4 #define mt(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 typedef long long LL;
  7 const double pi=acos(-1.0);
  8 const double eps=1e-8;
  9 const int inf=0x3f3f3f3f;
 10 const int M=1e3+10;
 11 class KMP { ///模式匹配(kmp)O(ls+lp)
 12     typedef char typec;///文本元素的類型
 13     static const int MV=1e3+10;///字符串的長度
 14     int next[MV];
 15 public:///匹配串長度 ls,str 存待匹配文本,模式串長度 lp,pat 存模式串
 16     int kmp(int ls,typec str[],int lp,typec pat[],int res[]) { ///返回匹配次數,res 中存儲每一個匹配的初始位置
 17         int i=0,j=-1,cnt=0;
 18         next[0]=-1;
 19         while(i<lp) {
 20             if(j==-1||pat[i]==pat[j]) {
 21                 next[++i]=++j;
 22                 continue;
 23             }
 24             j=next[j];
 25         }
 26         i=j=0;
 27         while(i<ls) {
 28             while(j!=lp&&str[i]==pat[j]) {
 29                 i++;
 30                 j++;
 31             }
 32             if(!j) {
 33                 i++;
 34                 continue;
 35             }
 36             if(j==lp) {
 37                 res[cnt++]=i-j;
 38             }
 39             j=next[j];
 40         }
 41         return cnt;
 42     }
 43 } gx;
 44 int n,m,x,y;
 45 char a[M][M];
 46 char b[M][M];
 47 int la[M];
 48 int lb[M];
 49 bitset<1000> b1,b2;
 50 int res[M];
 51 int solve(){
 52     for(int i=0;i<n;i++){
 53         la[i]=strlen(a[i]);
 54     }
 55     for(int i=0;i<x;i++){
 56         lb[i]=strlen(b[i]);
 57     }
 58     int sum=0;
 59     for(int i=0;i+x-1<n;i++){
 60         b1.reset();
 61         for(int j=0;j<m;j++){
 62             b1.set(j);
 63         }
 64         for(int j=0;j<x;j++){
 65             int time=gx.kmp(la[i+j],a[i+j],lb[j],b[j],res);
 66             if(time==0){
 67                 b1.reset();
 68                 break;
 69             }
 70             b2.reset();
 71             for(int k=0;k<time;k++){
 72                 b2.set(res[k]);
 73             }
 74             b1&=b2;
 75             if(b1.count()==0) break;
 76         }
 77         sum+=b1.count();
 78     }
 79     return sum;
 80 }
 81 int main() {
 82 #ifdef txtout
 83     freopen("in.txt","r",stdin);
 84     freopen("out.txt","w",stdout);
 85 #endif // txtout
 86     int t;
 87     while(~scanf("%d",&t)) {
 88         while(t--){
 89             scanf("%d%d",&n,&m);
 90             for(int i=0;i<n;i++){
 91                 scanf("%s",a[i]);
 92             }
 93             scanf("%d%d",&x,&y);
 94             for(int i=0;i<x;i++){
 95                 scanf("%s",b[i]);
 96             }
 97             printf("%d\n",solve());
 98         }
 99     }
100     return 0;
101 }
View Code

 

 不用bitset會慢一些, 常數

  1 //#define txtout
  2 //#define debug
  3 #include<bits/stdc++.h>
  4 #define mt(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 typedef long long LL;
  7 const double pi=acos(-1.0);
  8 const double eps=1e-8;
  9 const int inf=0x3f3f3f3f;
 10 const int M=1e3+10;
 11 class KMP { ///模式匹配(kmp)O(ls+lp)
 12     typedef char typec;///文本元素的類型
 13     static const int MV=1e3+10;///字符串的長度
 14     int next[MV];
 15 public:///匹配串長度 ls,str 存待匹配文本,模式串長度 lp,pat 存模式串
 16     int kmp(int ls,typec str[],int lp,typec pat[],int res[]) { ///返回匹配次數,res 中存儲每一個匹配的初始位置
 17         int i=0,j=-1,cnt=0;
 18         next[0]=-1;
 19         while(i<lp) {
 20             if(j==-1||pat[i]==pat[j]) {
 21                 next[++i]=++j;
 22                 continue;
 23             }
 24             j=next[j];
 25         }
 26         i=j=0;
 27         while(i<ls) {
 28             while(j!=lp&&str[i]==pat[j]) {
 29                 i++;
 30                 j++;
 31             }
 32             if(!j) {
 33                 i++;
 34                 continue;
 35             }
 36             if(j==lp) {
 37                 res[cnt++]=i-j;
 38             }
 39             j=next[j];
 40         }
 41         return cnt;
 42     }
 43 } gx;
 44 int n,m,x,y;
 45 char a[M][M];
 46 char b[M][M];
 47 int la[M];
 48 int lb[M];
 49 bool b1[M];
 50 bool b2[M];
 51 int res[M];
 52 int solve(){
 53     for(int i=0;i<n;i++){
 54         la[i]=strlen(a[i]);
 55     }
 56     for(int i=0;i<x;i++){
 57         lb[i]=strlen(b[i]);
 58     }
 59     int sum=0;
 60     for(int i=0;i+x-1<n;i++){
 61         int one=m;
 62         for(int j=0;j<m;j++){
 63             b1[j]=true;
 64         }
 65         for(int j=0;j<x;j++){
 66             int time=gx.kmp(la[i+j],a[i+j],lb[j],b[j],res);
 67             if(time==0){
 68                 one=0;
 69                 break;
 70             }
 71             for(int k=0;k<m;k++){
 72                 b2[k]=false;
 73             }
 74             for(int k=0;k<time;k++){
 75                 b2[res[k]]=true;
 76             }
 77             for(int k=0;k<m;k++){
 78                 if(b1[k]&&b2[k]) continue;
 79                 if(b1[k]&&!b2[k]){
 80                     b1[k]=false;
 81                     one--;
 82                     if(one==0) break;
 83                 }
 84             }
 85             if(one==0) break;
 86         }
 87         sum+=one;
 88     }
 89     return sum;
 90 }
 91 int main() {
 92 #ifdef txtout
 93     freopen("in.txt","r",stdin);
 94     freopen("out.txt","w",stdout);
 95 #endif // txtout
 96     int t;
 97     while(~scanf("%d",&t)) {
 98         while(t--){
 99             scanf("%d%d",&n,&m);
100             for(int i=0;i<n;i++){
101                 scanf("%s",a[i]);
102             }
103             scanf("%d%d",&x,&y);
104             for(int i=0;i<x;i++){
105                 scanf("%s",b[i]);
106             }
107             printf("%d\n",solve());
108         }
109     }
110     return 0;
111 }
View Code

 

ac自動機 need to write.

 

 

 

 

end

相關文章
相關標籤/搜索