題意:Tz養了一羣倉鼠,他們都有英文小寫的名字,如今Tz想用一個字母序列來表示他們的名字,只要他們的名字是字母序列中的一個子串就算,出現屢次能夠重複計算。如今Tz想好了要出現多少個名字,請你求出最短的字母序列的長度是多少。(n <= 200, m <= 1e9)ios
思路:首先能夠處理出g[a][b]表示b接在a後面的長度(即重複部分以前都不算)ide
那麼就能夠轉化成求長度m-1的最短路。ui
假設dis[i][a][b]爲通過i步a走到b的最短路,那麼dis[i][a][b] = min(dis[i/2][a][c] + dis[i-i/2][c][b]) (1<=c<=n)spa
那麼是否是就能夠利用快速冪的思想了。。code
前面求g[a][b]可利用hash判斷是否同樣blog
code:string
1 /* 2 * Author: Yzcstc 3 * Created Time: 2014/11/12 20:54:48 4 * File Name: hamsters.cpp 5 */ 6 #include<cstdio> 7 #include<iostream> 8 #include<cstring> 9 #include<cstdlib> 10 #include<cmath> 11 #include<algorithm> 12 #include<string> 13 #include<map> 14 #include<set> 15 #include<vector> 16 #include<queue> 17 #include<stack> 18 #include<ctime> 19 #define M0(x) memset(x, 0, sizeof(x)) 20 #define repf(i, a, b) for (int i = (a); i <= (b); ++i) 21 #define Inf 0x7fffffff 22 #define M 10007 23 using namespace std; 24 typedef long long ll; 25 const int maxn = 204; 26 int n, m; 27 char str[120000]; 28 vector<int> hs[210]; 29 int sz[maxn], pw[120000]; 30 ll A[maxn][maxn], B[maxn][maxn]; 31 ll s[maxn], tmp[maxn]; 32 33 inline int Hash(const int &p, const int& l, const int& r){ 34 return hs[p][r] - hs[p][l-1] * pw[r-l+1]; 35 } 36 37 void init(){ 38 int len, v; 39 repf(i, 1, n){ 40 scanf("%s", str + 1); 41 sz[i] = len = strlen(str + 1); 42 hs[i].push_back(v = 0); 43 repf(j, 1, len) 44 v = v * M + str[j], hs[i].push_back(v); 45 } 46 } 47 48 void modify(ll *s, ll A[][maxn]){ 49 memset(tmp, 0x3f, sizeof(tmp)); 50 // cout << tmp[0] << endl; 51 for (int i = 1; i <= n; ++i) 52 for (int j = 1; j <= n; ++j) 53 tmp[j] = min(tmp[j], s[i] + A[i][j]); 54 repf(i, 1, n) s[i] = tmp[i]; 55 } 56 57 void modify(ll A[][maxn]){ 58 memset(B, 0x3f, sizeof(B)); 59 repf(k, 1, n) repf(i, 1, n) repf(j, 1, n) 60 B[i][j] = min(B[i][j], A[i][k] + A[k][j]); 61 repf(i, 1, n) repf(j, 1, n) A[i][j] = B[i][j]; 62 } 63 64 void quick(int n){ 65 for (;n>0; n>>=1){ 66 if (n & 1) modify(s, A); 67 modify(A); 68 } 69 } 70 71 void solve(){ 72 repf(i, 1, n) repf(j, 1, n){ 73 A[i][j] = sz[j]; 74 for (int k = max(2, sz[i]-sz[j]+2); k <= sz[i]; ++k) 75 if (Hash(i, k, sz[i]) == Hash(j, 1, sz[i]-k+1)){ 76 A[i][j] = sz[j] - (sz[i]-k+1); break; 77 } 78 } 79 repf(i, 1, n) s[i] = sz[i]; 80 quick(--m); 81 ll ans = 1LL<<62; 82 // cout << ans << endl; 83 repf(i, 1, n) ans = min(ans, s[i]); 84 cout << ans << endl; 85 } 86 87 int main(){ 88 pw[0] = 1; 89 repf(i, 1, 100000) pw[i] = pw[i-1] * M; 90 while (scanf("%d%d", &n, &m) != EOF){ 91 init(); 92 solve(); 93 } 94 return 0; 95 }