https://codeforces.com/problemset/problem/963/Dnode
length distnctios
number <= sqrt(1e5)=316數組
全部串t出現次數<=1e5*315spa
對於某個串t出現的位置 遞增code
ac自動機一個點惟一指向另一個點blog
記錄須要合併的子孫下標,該節點已有的位置string
對於目標點,對數組進行合併。it
詳見代碼io
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方法ast
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))