题意
给出n个字符串,每个字符串有一个权值wi 有q个操作,操作有两种 1 x y 将字符串x的权值变为y 2 x 查询操作,输出以字符串x为后缀,且权值小于等于wx的字符串个数。其中n<=1000 每个字符串长度<=1000 询问q<=80000。
分析
n并不大,但是q太大了。如果暴力的话,每次查询都是o(n*len)的,肯定不行。
等等,谁说不行?我试试 emmm。。。爆过去了????下面是瞎几把爆的代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 6 using namespace std; 7 const int maxn=1000+10; 8 int len[maxn],w[maxn]; 9 char s[maxn][maxn]; 10 int T,n,q; 11 12 int main(){ 13 scanf("%d",&T); 14 for(int t=1;t<=T;t++){ 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++){ 17 scanf("%s",s[i]); 18 scanf("%d",&w[i]); 19 len[i]=strlen(s[i]); 20 } 21 scanf("%d",&q); 22 int opt; 23 for(int i=1;i<=q;i++){ 24 scanf("%d",&opt); 25 if(opt==1){ 26 int x,y; 27 scanf("%d%d",&x,&y); 28 w[x]=y; 29 }else if(opt==2){ 30 int x; 31 scanf("%d",&x); 32 int ans=0; 33 for(int j=1;j<=n;j++){ 34 if(w[j]>w[x])continue; 35 if(len[j]<len[x])continue; 36 bool ok=1; 37 for(int k=len[j]-1,l=len[x]-1;l>=0;k--,l--){ 38 if(s[x][l]!=s[j][k]){ 39 ok=0; 40 break; 41 } 42 } 43 if(ok){ 44 ans++; 45 // cout<<j<<endl; 46 } 47 } 48 printf("%d ",ans); 49 } 50 } 51 } 52 return 0; 53 }
好吧好吧,上面那个不算,我们重新来想···
后缀嘛,后缀数组?咳,我就知道名字而已不会。。想点会的。。
字典树行不行?我们只要把字符串倒着插进去就可以用统计前缀的方法来统计后缀了。
w这个限制怎么办?
我们在字典树上每一个字符串结尾维护一个vector···这样··时间复杂度是多少?均摊下应该是···可以的···吧?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6 using namespace std; 7 const int maxn=1000+10; 8 int ch[maxn*maxn][30],W[maxn]; 9 char s[maxn][maxn]; 10 int val[maxn*maxn]; 11 vector<int>G[maxn*maxn]; 12 int T,n,q,sz; 13 void insert(char *s,int w){ 14 int len=strlen(s); 15 int u=0; 16 for(int i=0;i<len;i++){ 17 int id=s[i]-'a'; 18 if(!ch[u][id]){ 19 ch[u][id]=++sz; 20 } 21 u=ch[u][id]; 22 } 23 G[u].push_back(w); 24 return ; 25 } 26 void tra(int u){ 27 /* if(G[u].size()!=0){ 28 for(int i=0;i<G[u].size();i++){ 29 printf("%d ",G[u][i]); 30 } 31 return; 32 }*/ 33 for(int i=0;i<26;i++){ 34 if(ch[u][i]){ 35 printf("%c",i+'a'); 36 tra(ch[u][i]); 37 } 38 } 39 return; 40 } 41 int ans; 42 void check(int u,int k){ 43 if(G[u].size()){ 44 for(int i=0;i<G[u].size();i++){ 45 if(W[G[u][i]]<=W[k]){ 46 ans++; 47 } 48 } 49 } 50 for(int i=0;i<26;i++){ 51 if(ch[u][i]) 52 check(ch[u][i],k); 53 } 54 return; 55 } 56 void solve(int k){ 57 int u=0; 58 ans=0; 59 for(int i=strlen(s[k])-1;i>=0;i--){ 60 int id=s[k][i]-'a'; 61 if(!ch[u][id]){ 62 return ; 63 } 64 u=ch[u][id]; 65 } 66 check(u,k); 67 return ; 68 } 69 int main(){ 70 scanf("%d",&T); 71 for(int t=1;t<=T;t++){ 72 scanf("%d",&n); 73 for(int i=0;i<=1000*1000;i++)G[i].clear(); 74 memset(val,0,sizeof(val)); 75 memset(ch,0,sizeof(ch)); 76 sz=0; 77 char s1[maxn]; 78 int x; 79 for(int i=1;i<=n;i++){ 80 scanf("%s%d",s[i],&W[i]); 81 for(int j=0;j<strlen(s[i]);j++){ 82 s1[j]=s[i][strlen(s[i])-1-j]; 83 } 84 s1[strlen(s[i])]='