zoukankan      html  css  js  c++  java
  • Frequency of String CodeForces

    http://codeforces.com/contest/963/problem/D

    题解:https://www.cnblogs.com/Blue233333/p/8881614.html

    记M为n个串的总长,L为s的长度

    询问串的不同的长度只会有sqrt(M)级别个

    (最差的情况是串长为1,2,3,...,x,此时M=(x+1)x/2,因此x是sqrt(M)级别的)

    s的子串中,长度为特定值k的子串个数是L级别的,

    由于各个字符串互不相同,这就相当于n个串中所有长度为k的串,分别计算出它们在s中出现次数,各个计算结果的和是L级别的

    因此只要设计对于每一个询问串都是O(串长+出现次数)的算法就行了


    花了好长时间写了个后缀自动机字符串匹配啊。。。。莫不是搞复杂了

    代码1.(using连用多个是c++17的,曾经还CE了)

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<set>
      5 #include<queue>
      6 using namespace std;
      7 typedef long long LL;
      8 char s[100010],ss[100100];
      9 int ll,x[100100],l2;
     10 int pp[100100];
     11 vector<int> vv[200100];
     12 set<int> sss[200100];
     13 int n,ans[100100];
     14 int lll[100100];
     15 namespace SAM
     16 {
     17     int mem,np,root;
     18     int len[200100],par[200100];
     19     int trans[200100][26];
     20     int posl[200100],posr[200100];
     21     void append(int ch)
     22     {
     23         int p=np;np=++mem;len[np]=len[p]+1;
     24         for(;p&&!trans[p][ch];p=par[p])    trans[p][ch]=np;
     25         if(!p)    par[np]=root;
     26         else
     27         {
     28             int q=trans[p][ch];
     29             if(len[q]==len[p]+1)    par[np]=q;
     30             else
     31             {
     32                 int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq;
     33                 memcpy(trans[nq],trans[q],sizeof(trans[nq]));len[nq]=len[p]+1;
     34                 for(;p&&trans[p][ch]==q;p=par[p])    trans[p][ch]=nq;
     35             }
     36         }
     37     }
     38     void build()
     39     {
     40         np=root=++mem;
     41         int i,now;
     42         for(i=1;i<=ll;i++)    append(s[i]-'a'),pp[i]=np,sss[np].insert(i);
     43         for(i=1;i<=ll;i++)
     44         {
     45             for(now=pp[i];now!=root&&!posr[now]&&!posl[now];now=par[now])
     46             {
     47                 posl[now]=i-len[par[now]];posr[now]=i-len[now]+1;
     48             }
     49         }
     50     }
     51 }
     52 namespace ST
     53 {
     54     int ch[200100][26];
     55     using SAM::par;
     56     void build()
     57     {
     58         int i;
     59         for(i=1;i<=SAM::mem;i++)
     60         {
     61             if(par[i])
     62             {
     63                 ch[par[i]][s[SAM::posl[i]]-'a']=i;
     64             }
     65         }
     66     }
     67     /*
     68     void out()
     69     {
     70         int i,j,k;using SAM::len,SAM::posl,SAM::posr;
     71         for(i=1;i<=SAM::mem;i++)
     72         {
     73             for(j=0;j<26;j++)
     74             {
     75                 if(ch[i][j])
     76                 {
     77                     printf("%d %d ",i,ch[i][j]);
     78                     for(k=posl[ch[i][j]];k>=posr[ch[i][j]];k--)    putchar(s[k]);
     79                     puts("");
     80                 }
     81             }
     82         }
     83     }
     84     */
     85 }
     86 void work(int tt)
     87 {
     88     using SAM::root,SAM::posl,SAM::posr,ST::ch;
     89     int i,now=root,j,k;
     90     for(i=l2;i>=1;)
     91     {
     92         now=ch[now][ss[i]-'a'];
     93         if(!now)    return;
     94         for(j=i,k=posl[now];j>=1&&k>=posr[now];j--,k--)
     95             if(ss[j]!=s[k])
     96                 return;
     97         i-=posl[now]-posr[now]+1;
     98         //printf("b%d %d %d %d
    ",now,i,posl[now],posr[now]);
     99     }
    100     vv[now].push_back(tt);//printf("a%d
    ",now);
    101 }
    102 queue<int> q;int in[200100];
    103 void work2()
    104 {
    105     using SAM::mem,SAM::par;
    106     int i,j,t,l,r;vector<int> tmp;
    107     for(i=1;i<=mem;i++)    if(par[i])    in[par[i]]++;
    108     for(i=1;i<=mem;i++)    if(!in[i])    q.push(i);
    109     while(!q.empty())
    110     {
    111         t=q.front();q.pop();
    112         if(vv[t].size())
    113         {
    114             tmp.clear();
    115             for(auto k:sss[t])    tmp.push_back(k);
    116             //for(i=0;i<tmp.size();i++)    printf("%d ",tmp[i]);puts("");
    117         }
    118         for(auto p:vv[t])
    119         {
    120             for(i=0,j=x[p]-1;j<tmp.size();i++,j++)
    121             {
    122                 ans[p]=min(ans[p],tmp[j]-tmp[i]+lll[p]);
    123             }
    124         }
    125         if(par[t])
    126         {
    127             if(sss[par[t]].size()<sss[t].size())    swap(sss[par[t]],sss[t]);
    128             for(auto k:sss[t])    sss[par[t]].insert(k);
    129             sss[t].clear();
    130             in[par[t]]--;
    131             if(!in[par[t]])    q.push(par[t]);
    132         }
    133     }
    134 }
    135 int main()
    136 {
    137     int i;
    138     scanf("%s",s+1);ll=strlen(s+1);
    139     SAM::build();ST::build();
    140     //ST::out();return 0;
    141     scanf("%d",&n);
    142     for(i=1;i<=n;i++)
    143     {
    144         scanf("%d%s",&x[i],ss+1);l2=lll[i]=strlen(ss+1);
    145         work(i);
    146     }
    147     memset(ans,0x3f,sizeof(ans));
    148     work2();
    149     for(i=1;i<=n;i++)
    150         printf("%d
    ",ans[i]==0x3f3f3f3f?-1:ans[i]);
    151     return 0;
    152 }
    View Code

    代码2:

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<set>
      5 #include<queue>
      6 using namespace std;
      7 typedef long long LL;
      8 char s[100010],ss[100100];
      9 int ll,x[100100],l2;
     10 int pp[100100];
     11 vector<int> vv[200100];
     12 set<int> sss[200100];
     13 int n,ans[100100];
     14 int lll[100100];
     15 namespace SAM
     16 {
     17     int mem,np,root;
     18     int len[200100],par[200100];
     19     int trans[200100][26];
     20     int posl[200100],posr[200100];
     21     void append(int ch)
     22     {
     23         int p=np;np=++mem;len[np]=len[p]+1;
     24         for(;p&&!trans[p][ch];p=par[p])    trans[p][ch]=np;
     25         if(!p)    par[np]=root;
     26         else
     27         {
     28             int q=trans[p][ch];
     29             if(len[q]==len[p]+1)    par[np]=q;
     30             else
     31             {
     32                 int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq;
     33                 memcpy(trans[nq],trans[q],sizeof(trans[nq]));len[nq]=len[p]+1;
     34                 posl[nq]=posl[q];posr[nq]=posl[q]-(len[nq]-len[par[nq]])+1;posl[q]=posr[nq]-1;
     35                 for(;p&&trans[p][ch]==q;p=par[p])    trans[p][ch]=nq;
     36             }
     37         }
     38     }
     39     void build()
     40     {
     41         np=root=++mem;
     42         int i,now;
     43         for(i=1;i<=ll;i++)
     44         {
     45             append(s[i]-'a'),sss[np].insert(i);
     46             for(now=np;now!=root&&!posr[now]&&!posl[now];now=par[now])
     47             {
     48                 posl[now]=i-len[par[now]];posr[now]=i-len[now]+1;
     49             }
     50         }
     51     }
     52 }
     53 namespace ST
     54 {
     55     int ch[200100][26];
     56     using SAM::par;
     57     void build()
     58     {
     59         int i;
     60         for(i=1;i<=SAM::mem;i++)
     61         {
     62             if(par[i])
     63             {
     64                 ch[par[i]][s[SAM::posl[i]]-'a']=i;
     65             }
     66         }
     67     }
     68     /*
     69     void out()
     70     {
     71         int i,j,k;using SAM::len,SAM::posl,SAM::posr;
     72         for(i=1;i<=SAM::mem;i++)
     73         {
     74             for(j=0;j<26;j++)
     75             {
     76                 if(ch[i][j])
     77                 {
     78                     printf("%d %d ",i,ch[i][j]);
     79                     for(k=posl[ch[i][j]];k>=posr[ch[i][j]];k--)    putchar(s[k]);
     80                     puts("");
     81                 }
     82             }
     83         }
     84     }
     85     */
     86 }
     87 void work(int tt)
     88 {
     89     using SAM::root,SAM::posl,SAM::posr,ST::ch;
     90     int i,now=root,j,k;
     91     for(i=l2;i>=1;)
     92     {
     93         now=ch[now][ss[i]-'a'];
     94         if(!now)    return;
     95         for(j=i,k=posl[now];j>=1&&k>=posr[now];j--,k--)
     96             if(ss[j]!=s[k])
     97                 return;
     98         i-=posl[now]-posr[now]+1;
     99         //printf("b%d %d %d %d
    ",now,i,posl[now],posr[now]);
    100     }
    101     vv[now].push_back(tt);//printf("a%d
    ",now);
    102 }
    103 queue<int> q;int in[200100];
    104 void work2()
    105 {
    106     using SAM::mem,SAM::par;
    107     int i,j,t;vector<int> tmp;
    108     for(i=1;i<=mem;i++)    if(par[i])    in[par[i]]++;
    109     for(i=1;i<=mem;i++)    if(!in[i])    q.push(i);
    110     while(!q.empty())
    111     {
    112         t=q.front();q.pop();
    113         if(vv[t].size())
    114         {
    115             tmp.clear();
    116             for(auto k:sss[t])    tmp.push_back(k);
    117             //for(i=0;i<tmp.size();i++)    printf("%d ",tmp[i]);puts("");
    118         }
    119         for(auto p:vv[t])
    120         {
    121             for(i=0,j=x[p]-1;j<tmp.size();i++,j++)
    122             {
    123                 ans[p]=min(ans[p],tmp[j]-tmp[i]+lll[p]);
    124             }
    125         }
    126         if(par[t])
    127         {
    128             if(sss[par[t]].size()<sss[t].size())    swap(sss[par[t]],sss[t]);
    129             for(auto k:sss[t])    sss[par[t]].insert(k);
    130             sss[t].clear();
    131             in[par[t]]--;
    132             if(!in[par[t]])    q.push(par[t]);
    133         }
    134     }
    135 }
    136 int main()
    137 {
    138     int i;
    139     scanf("%s",s+1);ll=strlen(s+1);
    140     SAM::build();ST::build();
    141     //ST::out();return 0;
    142     scanf("%d",&n);
    143     for(i=1;i<=n;i++)
    144     {
    145         scanf("%d%s",&x[i],ss+1);l2=lll[i]=strlen(ss+1);
    146         work(i);
    147     }
    148     memset(ans,0x3f,sizeof(ans));
    149     work2();
    150     for(i=1;i<=n;i++)
    151         printf("%d
    ",ans[i]==0x3f3f3f3f?-1:ans[i]);
    152     return 0;
    153 }
    View Code

    还有一份看上去很高妙的bitset字符串匹配(不是自己写的,先记一下)

    来源:http://codeforces.com/contest/963/submission/37784765

     1 #include<bits/stdc++.h>
     2 #define N 100005
     3 using namespace std;
     4 bitset<N> b[26],tmp;
     5 char s[N],t[N];
     6 int main(){
     7     scanf("%s",s);
     8     int n=strlen(s);
     9     for (int i=0;i<n;i++)
    10         b[s[i]-'a'][i]=1;
    11     int Q; scanf("%d",&Q);
    12     while (Q--){
    13         int k; scanf("%d%s",&k,t);
    14         int m=strlen(t);
    15         tmp.set();
    16         for (int i=0;i<m;i++)
    17             tmp&=b[t[i]-'a']>>i;
    18         if (tmp.count()<k){
    19             puts("-1");
    20             continue;
    21         }
    22         vector<int> v;
    23         for (int i=tmp._Find_first();i<n;i=tmp._Find_next(i))
    24             v.push_back(i);
    25         int ans=1e9;
    26         for (int i=0;i+k-1<v.size();i++)
    27             ans=min(ans,v[i+k-1]-v[i]+m);
    28         printf("%d
    ",ans);
    29     }
    30 }
    View Code

    就是搞复杂了。。

    要找一个字符串,只要在后缀自动机上一位一位找过去,保证最后到达的一定也是后缀树上的对应节点。。。

      1 #pragma GCC diagnostic error "-std=c++11"
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<set>
      6 #include<queue>
      7 using namespace std;
      8 typedef long long LL;
      9 char s[100010],ss[100100];
     10 int ll,x[100100],l2;
     11 int pp[100100];
     12 vector<int> vv[200100];
     13 set<int> sss[200100];
     14 int n,ans[100100];
     15 int lll[100100];
     16 int teststet;
     17 int ssss;
     18 
     19 namespace SAM
     20 {
     21     int mem,np,root;
     22     int len[200100],par[200100];
     23     int trans[200100][26];
     24     void append(int ch)
     25     {
     26         int p=np;np=++mem;len[np]=len[p]+1;
     27         for(;p&&!trans[p][ch];p=par[p])    trans[p][ch]=np;
     28         if(!p)    par[np]=root;
     29         else
     30         {
     31             int q=trans[p][ch];
     32             if(len[q]==len[p]+1)    par[np]=q;
     33             else
     34             {
     35                 int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq;
     36                 memcpy(trans[nq],trans[q],sizeof(trans[nq]));len[nq]=len[p]+1;
     37                 for(;p&&trans[p][ch]==q;p=par[p])    trans[p][ch]=nq;
     38             }
     39         }
     40     }
     41     void build()
     42     {
     43         np=root=++mem;
     44         int i;
     45         for(i=1;i<=ll;i++)
     46         {
     47             append(s[i]-'a'),sss[np].insert(i);
     48         }
     49     }
     50 }
     51 void work(int tt)
     52 {
     53     using SAM::trans;
     54     int i,now=SAM::root;
     55     for(i=1;i<=l2;i++)
     56     {
     57         now=trans[now][ss[i]-'a'];
     58     }
     59     vv[now].push_back(tt);
     60 }
     61 queue<int> q;int in[200100];
     62 void work2()
     63 {
     64     using SAM::mem;using SAM::par;
     65     int i,j,t;vector<int> tmp;
     66     for(i=1;i<=mem;i++)    if(par[i])    in[par[i]]++;
     67     for(i=1;i<=mem;i++)    if(!in[i])    q.push(i);
     68     while(!q.empty())
     69     {
     70         t=q.front();q.pop();
     71         if(vv[t].size())
     72         {
     73             tmp.clear();
     74             for(auto k:sss[t])    tmp.push_back(k);
     75         }
     76         for(auto p:vv[t])
     77         {
     78             for(i=0,j=x[p]-1;j<tmp.size();i++,j++)
     79             {
     80                 ans[p]=min(ans[p],tmp[j]-tmp[i]+lll[p]);
     81             }
     82         }
     83         if(par[t])
     84         {
     85             if(sss[par[t]].size()<sss[t].size())    swap(sss[par[t]],sss[t]);
     86             for(auto k:sss[t])    sss[par[t]].insert(k);
     87             sss[t].clear();
     88             in[par[t]]--;
     89             if(!in[par[t]])    q.push(par[t]);
     90         }
     91     }
     92 }
     93 int main()
     94 {
     95     int i;
     96     scanf("%s",s+1);ll=strlen(s+1);
     97     SAM::build();
     98     scanf("%d",&n);
     99     for(i=1;i<=n;i++)
    100     {
    101         scanf("%d%s",&x[i],ss+1);l2=lll[i]=strlen(ss+1);
    102         work(i);
    103     }
    104     int aefsaf;
    105     memset(ans,0x3f,sizeof(ans));
    106     work2();
    107     for(i=1;i<=n;i++)
    108         printf("%d
    ",ans[i]==0x3f3f3f3f?-1:ans[i]);
    109     return 0;
    110 }
    View Code
  • 相关阅读:
    PHP form 表单传参明细研究
    php返回数据库查询时出现Resource id #2
    AJAX避免服务器调用上个页面缓存的办法
    错误提示sudo: no tty present and no askpass program specified Sorry, try again.
    lua创建文件和文件夹
    ngx.lua中遇到的小问题2
    [Puzzle] 蚂蚁路线碰撞问题
    [问题记录] 操作符连写
    [工具] XMind
    Qt Creator快捷键
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8994810.html
Copyright © 2011-2022 走看看