[JZOJ 3747] [7.14] Problem C analog NOI2014

Description

Gene cluster is ACGT4 letters, we have a sequence of length n, S. Gene Wants to know the length of a gene string m, the longest common subsequence S are 0; 1;; each of several strings of n.

The remainder output answers to 10 ^ 9 + 7.

Input

The first line of a string S. The second line a positive integer m.

Output

row n + 1, i + 1 th row common subsequence S represents the remainder of a few about 10 ^ 7 + 9 i of the string.

Sample Input

GTC

10

Sample Output

1

22783

528340

497452

Data Constraint

10% of the data n <= 3; m <= 10.

50% of the data n <= 6; m <= 100.

100% data n <= 10; m <= 1000.

Thinking

We can consider the request for the longest common subsequence of two strings dp: f [i, j] represents the first sequence to i, the second string to the longest common subsequence j. For two strings, if the array f [i] is exactly the same, they impact on the back is exactly the same, so we can set two-dimensionally: F [i, j], and to represent our current i, f [i] state j is a number of programs, but set so that the state of the second dimension is 10 10 . We found a f [i, j] will not [i, j-1] is smaller than F, and a maximum ratio of f [i, j-1] over, so we can take a reset state when the difference, it becomes 2 10 .

Code

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 1050,Mo = 1000000007;

char s[12];
int f[MAXN][MAXN],s1[12],F[12],Nt[12],No[12],N,M;

int max(int a,int b) {return a > b ? a : b;}

int main()
{
	scanf("%s",s);
	N = strlen(s);
	for(int i = 0;i < N;i ++)
		if (s[i] == 'A') s1[i + 1] = 1; else if (s[i] == 'C') s1[i + 1] = 2; else
			if (s[i] == 'G') s1[i + 1] = 3; else s1[i + 1] = 4;
	scanf("%d", &M);
	f[0][0] = 1;
	for(int i = 0;i < M;i ++)
		for(int j = 0;j < (1 << N);j ++)
			if (f[i][j])
				for(int z = 1;z <= 4;z ++)
				{
					for(int k = 1;k <= N;k ++) Nt[k] = 0;
					for(int tmp = j,k = 0;tmp;tmp /= 2) Nt[N - (++ k) + 1] = tmp % 2;
					for(int p = 1;p <= N;p ++) Nt[p] += Nt[p - 1];
					int tmp = 0;
					for(int k = 1;k <= N;k ++)
					{
						No[k] = max(No[k - 1],Nt[k]);
						if (z == s1[k]) No[k] = max(No[k],Nt[k - 1] + 1);
						tmp = tmp * 2 + (No[k] - No[k - 1]);
					}
					f[i + 1][tmp] = (f[i + 1][tmp] + f[i][j]) % Mo;
				}
	for(int i = 0;i < (1 << N);i ++)
	{
		int c = 0;for(int tmp = i;tmp;tmp /= 2) c += tmp % 2;
		F[c] = (F[c] + f[M][i]) % Mo;
	}
	for(int i = 0;i <= N;i ++) printf("%d\n",F[i]);
}
Published 703 original articles · won praise 392 · Views 140,000 +

Guess you like

Origin blog.csdn.net/Eric1561759334/article/details/104083158