zoukankan      html  css  js  c++  java
  • 3.3 字符串(1)

    Trie 前缀树 字典树  

    例题11  LA 3942 http://acm.hust.edu.cn/vjudge/problem/22109

    字典树第一个例题我用set水过,先记录这个版本吧,题意是,给一个串,还有一些短串的集合,问有多少种不同的拆分方法使得拆分完后,每个子串都在集合中。

    dp[len] 表示前len个有多少拆分法 dp[0]=1, 前0个字符有一种拆分法,空嘛。  dp[len] 就是答案,  转移就是, 如果接下来一段在集合中,那么就可以转移到长度加这段的长度。

    起点有la=3e5,,对每一个起点,加的串可能有lbi=100,都要枚举,接下来就是判断这个串是否存在,用hash值判,o1,set查询logn ,n=4000, 总体复杂度 la*lb*logn 飘过2700ms。

     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
    ",cas++,solve());
    77     }
    78     return 0;
    79 }
    View Code

     字典树特别快72ms.  与上一种方法的差别就在于,用字典树存小串集合,然后还是枚举起点, 更新的时候就在字典树里更新, 遇到一个串就更新一个dp, 最坏情况复杂度 la*lb.

      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
    ",cas++,solve());
    104     }
    105     return 0;
    106 }
    View Code

    例题12 uva 11732 http://acm.hust.edu.cn/vjudge/problem/28438

    题意, 给n个字符串,用题目中的strcmp两两比较,需要执行多少次==判断.

    暴力n2枚举, 最坏len计算次数.超时.

    字典树做法,先把所有串插入字典树, 然后枚举一个串去字典树中查询, 对于串的每一位,都需要和所有串执行一次==,通过字典树节点记录的次数可以o1累加, 然后和该位置相等的串会多执行一次=='',也可以o1得到.

    因为也会比较一次,而字典树中我没存,所以我在每个串后面加个#表示,这样比较时不需要特判他了.  然后每个串会多算一个和自己的次数,  扣去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
    ",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
    ",cas++);
    69         for(int i=0; i<answer.size(); i++) {
    70             printf("%d %d
    ",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
    ",cas++);
    46         for(int i=0; i<answer.size(); i++) {
    47             printf("%d %d
    ",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
    ",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
    ",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
    ",solve());
    108         }
    109     }
    110     return 0;
    111 }
    View Code

    ac自动机 need to write.

    end

  • 相关阅读:
    bzoj3574[Hnoi2014]抄卡组
    bzoj3576[Hnoi2014]江南乐
    [GDKOI2016]小学生数学题
    bzoj3572[Hnoi2014]世界树
    bzoj3571[Hnoi2014]画框
    bzoj3573[Hnoi2014]米特运输
    指数循环节
    bzoj4013[HNOI2015]实验比较
    bzoj4012[HNOI2015]开店
    bzoj1095[ZJOI2007]Hide 捉迷藏
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/5768391.html
Copyright © 2011-2022 走看看