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

题目链接: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

 

posted @ 2017-10-10 19:31  bin_gege  阅读(236)  评论(0编辑  收藏  举报