10.31T4 HAOI2010最长公共子序列 计数+容斥原理

2775 -- 【HAOI2010】最长公共子序列

Description

  字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij = yj。例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。
  对给定的两个字符序列,求出他们最长的公共子序列长度,以及最长公共子序列个数。

Input

  第1行为第1个字符序列,都是大写字母组成,以”.”结束。长度小于5000。
  第2行为第2个字符序列,都是大写字母组成,以”.”结束,长度小于5000。

Output

  第1行输出上述两个最长公共子序列的长度。
  第2行输出所有可能出现的最长公共子序列个数,答案可能很大,只要将答案对100,000,000求余即可。

Sample Input

ABCBDAB.
BACBBD.

Sample Output

4
7

Hint

  说明:若答对第1问,则得到总分的40%,若答对第2问,则得到总分的60%,若两问都对则得到100%分数。

Source

xinyue
 
 
 
写不动题解了,滚一下数组节省空间
code:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 using namespace std;
 5 int g[5005][5005],f[5005][5005];
 6 int main() {
 7     string A,B;
 8     cin>>A>>B;
 9     A=' '+A,B=' '+B;
10     int lena=A.size()-2;
11     int lenb=B.size()-2;int now=0;
12 //    for(int i=1; i<=lena; i++)g[i][0]=1;
13     for(int i=0; i<=lenb; i++)g[0][i]=1;
14     for(int i=1; i<=lena; i++) {
15         now^=1;g[now][0]=1;
16         for(int j=1; j<=lenb; j++) {
17             g[now][j]=0;
18             f[now][j]=max(f[now^1][j],max(f[now][j-1],(f[now^1][j-1]+1)*(A[i]==B[j]?1:0)));
19             if(f[now][j]==f[now^1][j])g[now][j]+=g[now^1][j];
20             if(f[now][j]==f[now][j-1])g[now][j]+=g[now][j-1];
21             if(f[now][j]==f[now^1][j-1]+1&&A[i]==B[j])g[now][j]+=g[now^1][j-1];
22             if(f[now][j]==f[now^1][j-1]&&A[i]!=B[j])g[now][j]-=g[now^1][j-1];
23             g[now][j]%=100000000;
24         }
25     }
26     cout<<f[now][lenb]<<"\n"<<g[now][lenb];
27     return 0;
28 }

over

posted @ 2018-10-31 20:40  saionjisekai  阅读(193)  评论(0编辑  收藏  举报