题目链接:
https://cn.vjudge.net/contest/313499#problem/L
SOLUTION:
对于题意,要求最短的表达式,当用最小循环元来表示一个字符串时,其表达式才最短。
对于字符串S自匹配求出next数组,分析可以发现:当i-next[i]能整除i时,S[1~i-next[i]]就是S[1~i]的最小循环元。它的最大循环次数就是i/(i-next[i])。
接下来枚举所有字串的最小循环元,取最优。
CODE:
#include "bits/stdc++.h" using namespace std; const int maxn = 1e4 + 100; int n; char s[maxn]; int Next[maxn]; int f[maxn]; void getnext(char str[], int l) { for (int i = 2, j = 0; i <= l; i++) { while (j > 0 && str[i] != str[j + 1]) j = Next[j]; if (str[i] == str[j + 1]) j++; Next[i] = j; } } int main() { //freopen("input.txt", "r", stdin); int N, now, temp; scanf("%d", &N); while (N--) { scanf("%s", s + 1); n = strlen(s + 1); for (int i = 0; i <= n; i++) f[i] = i; for (int i = 1; i <= n; i++) { getnext(s + i - 1, n - i + 1); for (int j = i; j <= n; j++) { f[j]=min(f[j],j-i+1+f[i-1]); now = j - i + 1; if (now % (now - Next[now]) == 0) { f[j] = min(f[j], f[i - 1] + now - Next[now]); } } } printf("%d ", f[n]); } return 0; }