codevs2019 Uva10029 递变阶梯

提交地址:[codevs][Uva]

题目描述 

      递变是指通过增加、减少或改变单词x中的一个字母,使它变成字典中的另一个单词y。比如将dig变成dog,将dog变成do都是递变。递变阶梯是一个按字典序排列的单词序列w1,w2,...wn,满足对于从1到n-1的所有i,单词wi到wi+1都是一次递变。相同的单词之间不能递变。n=15000

      给出一部字典,你要计算其中最长的递变阶梯。

题目分析

  容易看出这是一个DAG的最长路(类似LIS),那么我们可以想到一个O(n^2)的算法,显然超时.

  换个方式想,如果我们枚举每个字符串可以变成的另一个字符串,再判断是否在里面,那么容易发现不会超时(15000*16*26),那么我们可以这样建图,然后走DAG最长路,很可惜我下面这份代码由于Hash的特殊性,无法通过Uva,仅能通过Codevs

题目代码

  

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 string str[32000];
 4 const int base = 131;
 5 typedef unsigned long long ull;
 6 ull f[32000][22];
 7 ull base_pow[22],ans[32000];
 8 ull num[20000000],pla[20000000];
 9 ull mod = 14233333;
10 
11 int main(){
12     int n=0;
13     while(cin>>str[++n])if(str[n]==str[n-1])n--;
14     n--;
15     base_pow[0]=1;
16     for(int i=1;i<=16;i++)base_pow[i]=base_pow[i-1]*base;
17     for(int i=1;i<=n;i++){
18     f[i][0]=str[i][0]-'a'+1;
19     for(int j=1;j<str[i].length();j++)
20         f[i][j]=f[i][j-1]*base+str[i][j]-'a'+1;
21     num[f[i][str[i].length()-1]%mod]=1;
22     pla[f[i][str[i].length()-1]%mod]=i;
23     }
24     for(int i=1;i<=n;i++)ans[i]=1;
25     for(int i=1;i<=n;i++){
26     string s=str[i];
27     for(int j=0;j<s.length();j++){
28         ull sd = f[i][s.length()-1];
29         sd-=f[i][j]*base_pow[s.length()-j-1];
30         if(j-1>=0)
31         sd+=f[i][j-1]*base_pow[s.length()-j-1];
32         if(num[sd%mod]&&pla[sd%mod]<i&&s.length()-1>0)
33         ans[i]=max(ans[i],ans[pla[sd%mod]]+1);
34     }
35     for(int j=0;j<s.length();j++){
36         ull sd = f[i][s.length()-1];
37         sd-=f[i][j]*base_pow[s.length()-j-1];
38         if(j-1>=0)
39         sd+=f[i][j-1]*base_pow[s.length()-j-1];
40         if(num[sd%mod]&&pla[sd%mod]>i&&s.length()-1>0)
41         ans[pla[sd%mod]]=max(ans[pla[sd%mod]],ans[i]+1);
42     }
43     for(int j=0;j<str[i].length();j++){
44         ull sd;
45         for(int k=1;k<=26;k++){
46         sd = f[i][s.length()-1];
47         sd-=f[i][j]*base_pow[s.length()-j-1];
48         sd+=k*base_pow[s.length()-j-1];
49         if(j-1>=0)
50             sd+=f[i][j-1]*base_pow[s.length()-j];
51         if(num[sd%mod]&&pla[sd%mod]>i)
52             ans[pla[sd%mod]]=max(ans[pla[sd%mod]],ans[i]+1);
53         }
54     }
55     }
56     ull maxx=0;
57     for(int i=1;i<=n;i++){
58     maxx=max(maxx,ans[i]);
59     }
60     cout<<maxx;
61 }
原文地址:https://www.cnblogs.com/1-1-1-1/p/6550132.html