1. 程式人生 > >Russian Code Cup 2017 - Finals B. Similar Words(hash+樹形dp)

Russian Code Cup 2017 - Finals B. Similar Words(hash+樹形dp)

!= auto ces 現在 amp 鏈接 blog none fine

題目鏈接:Russian Code Cup 2017 - Finals B. Similar Words

題意:

給你n個字符串,現在讓你構造一個集合X。

1.使得X的每個元素都是這n個字符串中的前綴。

2.X中任意兩個元素都不相似(即一個字符串去掉第一個字符後不是另一個字符串)

題解:

我們將所有的前綴取出來,考慮將相似的連邊。這裏可以發現一個字符串去掉首字符後只有唯一的一個字符串。

所有將相似的連邊後,就形成了一個森林。(判相似可以用hash,可以用AC自動機)

然後建完邊後就是一個樹形dp了。

這裏hash容易被卡,雙hash1.5s飄過。

技術分享
 1 #include<bits/stdc++.h>
 2
#define F(i,a,b) for(int i=(a);i<=(b);++i) 3 #define mst(a,b) memset(a,b,sizeof(a)) 4 using namespace std; 5 typedef long long uu; 6 typedef pair<pair<uu,uu>,int>P; 7 namespace str_hash 8 { 9 const uu sd=1e9+7,D=1e9+9,N=1e6+7; 10 uu b[N],B[N]; 11 void init(){ 12 b[0
]=1;F(i,1,N-1)b[i]=(b[i-1]*31)%sd; 13 B[0]=1;F(i,1,N-1)B[i]=(B[i-1]*31)&((1<<30)-1); 14 } 15 struct STR{ 16 int l; 17 uu *h,*h2; 18 void ins(char *s){ 19 int len=strlen(s+1); 20 h=new uu[len+1]; 21 h2=new uu[len+1]; 22
for(h[0]=0,h2[0]=0,l=1;s[l];l++) 23 { 24 h[l]=(h[l-1]*31+s[l])%sd; 25 h2[l]=(h2[l-1]*31+s[l])&((1<<30)-1); 26 } 27 l--; 28 } 29 pair<uu,uu> ask(int l,int r){ 30 return pair<uu,uu>((h[r]-h[l-1]*b[r-l+1]%sd+sd)%sd,(h2[r]-(h2[l-1]*B[r-l+1]&((1<<30)-1))+((1<<30)-1))&((1<<30)-1)); 31 } 32 }str[N]; 33 } 34 35 using namespace str_hash; 36 int t,n; 37 char s[N]; 38 vector<int>g[N]; 39 set<P>st; 40 int dp[N][2],in[N],vis[N]; 41 42 void dfs(int x) 43 { 44 dp[x][0]=1,dp[x][1]=0; 45 for(auto &it:g[x]) 46 { 47 dfs(it); 48 dp[x][0]+=dp[it][1]; 49 dp[x][1]+=max(dp[it][0],dp[it][1]); 50 } 51 } 52 53 54 int main(){ 55 init(),scanf("%d",&t); 56 while(t--) 57 { 58 scanf("%d",&n); 59 F(i,1,n) 60 { 61 scanf("%s",s+1); 62 str[i].ins(s); 63 } 64 int idx=0; 65 F(i,1,n)F(j,1,str[i].l) 66 { 67 ++idx; 68 pair<uu,uu> now=str[i].ask(1,j); 69 auto it=st.lower_bound(P(now,0)); 70 if(it!=st.end()&&it->first==now)vis[idx]=1; 71 else st.insert(P(now,idx)); 72 } 73 idx=0; 74 F(i,1,n)F(j,1,str[i].l) 75 { 76 ++idx; 77 if(j==1||vis[idx])continue; 78 pair<uu,uu> now=str[i].ask(2,j); 79 auto it=st.lower_bound(P(now,0)); 80 if(it!=st.end()&&it->first==now) 81 { 82 g[it->second].push_back(idx); 83 in[idx]++; 84 } 85 } 86 int ans=0; 87 F(i,1,idx)if(in[i]==0&&vis[i]==0) 88 { 89 dfs(i),ans+=max(dp[i][0],dp[i][1]); 90 } 91 printf("%d\n",ans); 92 st.clear(); 93 F(i,1,idx)dp[i][0]=dp[i][1]=0,g[i].clear(),vis[i]=in[i]=0; 94 } 95 return 0; 96 }
View Code

Russian Code Cup 2017 - Finals B. Similar Words(hash+樹形dp)