Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 1) D. Frequency of String

 

https://codeforces.com/problemset/problem/963/D

 

length distnct

number <= sqrt(1e5)=316

所有串t出现次数<=1e5*315

 

对于某个串t出现的位置 递增

 

ac自动机一个点唯一指向另外一个点

记录需要合并的子孙下标,该节点已有的位置

对于目标点,对数组进行合并。

详见代码

 

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 #include <vector>
 11 
 12 const double eps=1e-8;
 13 const ll inf=1e9;
 14 const ll mod=1e9+7;
 15 const int maxn=1e5+10;
 16 const int maxm=sqrt(100)+10;
 17 
 18 /**
 19 all string are distinct
 20 **/
 21 
 22 struct node
 23 {
 24     int num,ind;
 25     node *nex[26],*pre,*fail;
 26 }*tr,*be,*pos,*p,*td,*q[maxn];
 27 
 28 char s[maxn],str[maxn];
 29 int least[maxn],re[maxn];
 30 int head1,tail1,d1,q1[maxn],cnt_least;
 31 
 32 vector<int> hap[maxn],son[maxn],temp,temp1;
 33 ///son:记录有用的子孙节点的编号,只有处于目标点时才合并
 34 
 35 void arr_merge(int ind)
 36 {
 37     temp1.clear();
 38     vector<int>::iterator i=temp.begin(),j=hap[ind].begin(),i_end=temp.end(),j_end=hap[ind].end();
 39     while (i!=i_end && j!=j_end)
 40     {
 41         if (*i < *j)
 42             temp1.push_back(*i),i++;
 43         else
 44             temp1.push_back(*j),j++;
 45     }
 46     while (i!=i_end)
 47         temp1.push_back(*i),i++;
 48     while (j!=j_end)
 49         temp1.push_back(*j),j++;
 50     temp=temp1;
 51 }
 52 
 53 int main()
 54 {
 55     int n,N,len,i,d,head,tail,ind,num,ii,jj;
 56     vector<int>::iterator j;
 57     tr=new node();
 58     be=new node();
 59     tr->pre=be;
 60     tr->fail=be;
 61     be->fail=be;
 62     for (i=0;i<26;i++)
 63         be->nex[i]=tr;
 64 
 65     scanf("%s",s);
 66     scanf("%d",&n);
 67     for (N=1;N<=n;N++)
 68     {
 69         scanf("%d%s",&least[N],str);
 70         len=strlen(str);
 71         re[N]=strlen(str);
 72         pos=tr;
 73         for (i=0;i<len;i++)
 74         {
 75             d=str[i]-97;
 76             if (!pos->nex[d])
 77             {
 78                 p=new node();
 79                 pos->nex[d]=p;
 80                 p->pre=pos;
 81             }
 82             pos=pos->nex[d];
 83         }
 84         pos->num=N;
 85     }
 86 
 87     head=0,tail=1;
 88     q[1]=tr;
 89     while (head<tail)
 90     {
 91         head++;
 92         td=q[head];
 93         for (d=0;d<26;d++)
 94             if (td->nex[d])
 95             {
 96                 pos=td->fail;
 97                 while (!pos->nex[d])
 98                     pos=pos->fail;
 99                 td->nex[d]->fail=pos->nex[d];
100                 q[++tail]=td->nex[d];
101                 td->nex[d]->ind=tail;///
102             }
103     }
104 
105     len=strlen(s);
106     pos=tr;
107     for (i=0;i<len;i++)
108     {
109         d=s[i]-97;
110         while (!pos->nex[d])
111             pos=pos->fail;
112         pos=pos->nex[d];
113 
114         hap[pos->ind].push_back(i);
115     }
116 
117     for (i=tail;i>=1;i--)
118     {
119         pos=q[i];
120         ind=pos->ind;
121         num=pos->num;
122         if (num)
123         {
124             temp.clear();
125             head1=0,tail1=1;
126             q1[1]=ind;
127             while (head1<tail1)
128             {
129                 head1++;
130                 d1=q1[head1];
131                 if (!hap[d1].empty())
132                 {
133                     if (temp.empty())
134                         temp=hap[d1];
135                     else
136                         arr_merge(d1);
137                 }
138                 for (j=son[d1].begin();j!=son[d1].end();j++)
139                     q1[++tail1]=*j;
140             }
141             hap[ind]=temp;
142             son[ind].clear();
143 
144             cnt_least=inf;
145 //            printf("size =%d\n",hap[ind].size());
146             jj=hap[ind].size()-least[num];
147             for (ii=0;ii<=jj;ii++)
148                 cnt_least=min(cnt_least,hap[ind][ii+least[num]-1]-hap[ind][ii]);
149             if (cnt_least==inf)
150                 re[num]=-1;
151             else
152                 re[num]+=cnt_least;
153         }
154         if (!hap[ind].empty() || !son[ind].empty())
155             son[pos->fail->ind].push_back(ind);
156     }
157 
158     for (i=1;i<=n;i++)
159         printf("%d\n",re[i]);
160     return 0;
161 }

 

bitset方法

https://codeforces.com/contest/963/submission/37784765

代码中

记录文本串s某个字符的所有位置

在模式串中对于一个字符t[i],b[t[i]-'a']为所有可以对应的位置,左移i个单位;如果对于所有j,tmp某个位置都为1,则tmp该个位置为1,模式串t可以与s+j匹配。

时间复杂度O(length(s)*sum(length(t))

posted @ 2019-06-30 22:07  congmingyige  阅读(133)  评论(0编辑  收藏  举报