题目
题目大意给定一个字符串序列,求其有多少个“几乎相等”的序列。
题目中对“几乎相等”的定义为:
- 两个字符串序列中每种单词出现的数量需要相同
- 每种单词的第i个在两个序列中出现的位置相差不能超过1
根据这个定义,序列本身就是一个“几乎相等”序列。除此之外,任意交换原序列两个相邻的元素,得到的序列是一个“几乎相等”序列。但是参与交换的两个元素不能相同且其中不能有已经参与过交换的。
基于这个规则,我们可以使用dp来进行状态统计。
我们设状态 dp[i][0/1]表示前i位的方案数,0代表与上一个进行交换,1代表不与上一个进行交换。
于是不难得出下列转移方程:
d p [ i ] [ 0 ] = { 0 ( s t r [ i ] = s t r [ i − 1 ] ) d p [ i − 1 ] [ 1 ] ( s t r [ i ] ≠ s t r [ i − 1 ] ) dp[i][0] = \left\{\begin{matrix} 0 (str[i] = str[i - 1]) \\ dp[i - 1][1](str[i] ≠str[i-1]) \end{matrix}\right. dp[i][0]={
0(str[i]=str[i−1])dp[i−1][1](str[i]=str[i−1])
d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] + d p [ i − 1 ] [ 1 ] dp[i][1]= dp[i - 1][0] + dp[i - 1][1] dp[i][1]=dp[i−1][0]+dp[i−1][1]
不要忘记初始化:
d p [ 1 ] [ 0 ] = 0 dp[1][0]=0 dp[1][0]=0
d p [ 1 ] [ 1 ] = 1 dp[1][1]=1 dp[1][1]=1
答案就是:
a n s = d p [ n ] [ 0 ] + d p [ n ] [ 1 ] ans=dp[n][0]+dp[n][1] ans=dp[n][0]+dp[n][1]
不要忘记取模!!!!
代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1e5 + 50;
const int mo = 1e9 + 7;
long long dp[N][2];
char a[N][20];
int n,T;
int main(){
for(cin >> T;T;T--){
cin >> n;
for(int i = 1;i <= n;i++){
cin >> a[i];
}
dp[1][0] = 0;
dp[1][1] = 1;
for(int i = 2;i <= n;i++){
if(!strcmp(a[i],a[i - 1])){
dp[i][0] = 0;
}else{
dp[i][0] = dp[i - 1][1];
}
dp[i][1] = (dp[i - 1][0] + dp[i - 1][1]) % mo;
}
cout << (dp[n][0] + dp[n][1]) % mo<< endl;
}
}