String Factoring

Spotting patterns in seemingly random strings is a problem with many applications. E.g. in our efforts to understand the genome we investigate the structure of DNA strings. In data compression we are interested in finding repetitions, so the data can be represented more efficiently with pointers. Another plausible example arises from the area of artificial intelligence, as how to interpret information given to you in a language you do not know. The natural thing to do in order to decode the information message would be to look for recurrences in it. So if the SETI project (the Search for Extra Terrestrial Intelligence) ever get a signal in the H21-spectra, we need to know how to decompose it.
One way of capturing the redundancy of a string is to find its factoring. If two or more identical substrings A follow each other in a string S S S, we can represent this part of S S S as the substring A A A, embraced by parentheses, raised to the power of the number of its recurrences. E.g. the string D O O D O O DOODOO DOODOO can be factored as ( D O O ) 2 (DOO)^2 (DOO)2, but also as ( D ( O ) 2 ) 2 (D(O)^2)^2 (D(O)2)2. Naturally, the latter factoring is considered better since it cannot be factored any further. We say that a factoring is irreducible if it does not contain any consecutive repetition of a substring. A string may have several irreducible factorings, as seen by the example string P O P P O P POPPOP POPPOP. It can be factored as ( P O P ) 2 (POP)^2 (POP)2, as well as P O ( P ) 2 O P PO(P)^2OP PO(P)2OP. The first factoring has a shorter representation and motivates the following definition. The weight of a factoring, equals the number of characters in it, excluding the parentheses and the exponents. Thus the weight of ( P O P ) 2 (POP)^2 (POP)2 is 3 3 3, whereas P O ( P ) 2 O P PO(P)^2OP PO(P)2OP has weight 5 5 5. A maximal factoring is a factoring with the smallest possible weight. It should be clear that a maximal factoring is always an irreducible one, but there may still be several maximal factorings. E.g. the string A B A B A ABABA ABABA has two maximal factorings ( A B ) 2 A (AB)^2A (AB)2A and A ( B A ) 2 A(BA)^2 A(BA)2.
Input
The input consists of several rows. The rows each hold one string of at least one, but less than 80 80 80 characters from the capital alphabet A-Z. The input is terminated by a row containing the character ‘*’ only. There will be no white space characters in the input.
Output
For each string in the input, output one line containing the weight of a maximal factoring of the string.

Sample Input
PRATTATTATTIC
GGGGGGGGG
PRIME
BABBABABBABBA
ARPARPARPARPAR
*
Sample Output
6
1
5
6
5

区间 d p dp dp
f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i ] [ k ] + f [ k + 1 ] [ j ] , c a l c ( i , j ) ) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j],calc(i,j)) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j],calc(i,j))
其中 c a l c ( i , j ) calc(i,j) calc(i,j)可以利用前缀函数计算出最小周期。
时间复杂度为 O ( n 3 ) O(n^3) O(n3)

#include

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector
#define pii pair
#define mii unordered_map
#define msi unordered_map
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 85;
char a[N];
int n, f[N][N], Next[N];

inline void init() {
    repi(i, 1, n) {
        f[i][i] = 1;
        repi(j, i + 1, n)f[i][j] = INF;
    }
}

inline int calc(int l, int r) {
    int len = r - l + 1;
    for (register int i = 2, j = 0; i <= len; i++) {
        while (j && a[l - 1 + i] != a[l + j])j = Next[j];
        if (a[l - 1 + i] == a[l + j])j++;
        Next[i] = j;
    }
    return len % (len - Next[len]) ? len : f[l][l + len - Next[len] - 1];
}

inline int solve() {
    repi(l, 2, n)repi(i, 1, n - l + 1) {
            int j = i + l - 1;
            repi(k, i, j - 1)f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j]);
            f[i][j] = min(f[i][j], calc(i, j));
        }
    return f[1][n];
}

int main() {
    while (ss(a + 1), a[1] != '*') {
        n = strlen(a + 1);
        init();
        pi(solve());
    }
    return 0;
}

你可能感兴趣的:(ACM,前缀函数,区间dp)