1. 程式人生 > >Luogu P2679 子串

Luogu P2679 子串

題目描述

有兩個僅包含小寫英文字母的字串 AA 和 BB。

現在要從字串 AA 中取出 kk 個互不重疊的非空子串,然後把這 kk 個子串按照其在字串 AA 中出現的順序依次連線起來得到一個新的字串。請問有多少種方案可以使得這個新串與字串 BB 相等?

注意:子串取出的位置不同也認為是不同的方案。

輸入輸出格式

輸入格式:

 

第一行是三個正整數 n,m,kn,m,k,分別表示字串 AA 的長度,字串 BB 的長度,以及問題描述中所提到的 kk,每兩個整數之間用一個空格隔開。

第二行包含一個長度為 nn 的字串,表示字串 AA。

第三行包含一個長度為 mm 的字串,表示字串 BB。

 

輸出格式:

 

一個整數,表示所求方案數。

由於答案可能很大,所以這裡要求輸出答案對 10000000071000000007 取模的結果。

 

輸入輸出樣例

輸入樣例#1: 複製

6 3 1 
aabaab 
aab

輸出樣例#1: 複製

2

輸入樣例#2: 複製

6 3 2 
aabaab 
aab

輸出樣例#2:

 複製

7

輸入樣例#3: 複製

6 3 3 
aabaab 
aab

輸出樣例#3: 複製

7

說明

對於第 1 組資料:1≤n≤500,1≤m≤50,k=11≤n≤500,1≤m≤50,k=1;
對於第 2 組至第 3 組資料:1≤n≤500,1≤m≤50,k=21≤n≤500,1≤m≤50,k=2;
對於第 4 組至第 5 組資料:1≤n≤500,1≤m≤50,k=m1≤n≤500,1≤m≤50,k=m;
對於第 1 組至第 7 組資料:1≤n≤500,1≤m≤50,1≤k≤m1≤n≤500,1≤m≤50,1≤k≤m;
對於第 1 組至第 9 組資料:1≤n≤1000,1≤m≤100,1≤k≤m1≤n≤1000,1≤m≤100,1≤k≤m;
對於所有 10 組資料:1≤n≤1000,1≤m≤200,1≤k≤m1≤n≤1000,1≤m≤200,1≤k≤m。

 

字串的題除了純粹的字串就只有動態規劃了

這題明顯是動態規劃

4維狀態(因為我菜,3維不夠用)

f[i][j][k][0/1]表示A中匹配到i,B中匹配到j,取了k個子串,A中最後一個取或不取的方案

f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]

f[i][j][k][1]=f[i-1][j-1][k-1][1]+f[i-1][j-1][k-1][0]+f[i-1][j-1][k][1]

初值初始化一層

為了減小空間,開滾動陣列即可

#include<cstdio>
#define ll long long
const int p=1e9+7;
using namespace std;
 
const int N=1005; 
int n,m,q,now,s;
char a[N],b[N];
int f[2][N][N][2];
 
inline int get(int x)
{
    return x>=p?x-p:x;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    scanf("%s%s",a+1,b+1);
    now=s=0;
    for(int i=1;i<=n;i++)
    {
        now=1-now;
        for(int j=1;j<=m;j++)
            for(int k=1;k<=q;k++)
                f[now][j][k][0]=f[now][j][k][1]=0;
        f[now][1][1][0]=s;
        if(a[i]==b[1]) f[now][1][1][1]=1,s++;
        for(int j=2;j<=m;j++)
            for(int k=1;k<=q;k++)
            {
                f[now][j][k][0]=get(f[1-now][j][k][0]+f[1-now][j][k][1]);
                if(a[i]==b[j]) f[now][j][k][1]=get(get(f[1-now][j-1][k-1][1]+f[1-now][j-1][k-1][0])+f[1-now][j-1][k][1]);
            }
    }
    printf("%d\n",get(f[now][m][q][0]+f[now][m][q][1]));
    return 0;
}