题目:
题意:
现在有一个长度为
n
n
n的串
S
S
S,其中每一个字母都是前
m
m
m个小写字母
计算有多少个不同的长度为
n
n
n的
T
T
T(其中T也是由前
m
m
m个小写字母组成),并且
S
S
S与
T
T
T的
L
C
S
LCS
LCS为
n
−
1
n-1
n−1
L
C
S
LCS
LCS就是同时存在于
S
S
S和
T
T
T的最长子序列
分析:
首先考虑挖一个空再填一个字母。
这样方案数为
n
∗
m
−
n
n*m-n
n∗m−n
但是我们考虑
a
a
b
aab
aab这样的字符,无论挖掉哪个
a
a
a都是一样的,所有我们将其根据字母相同分为几个块
a
∣
b
b
∣
c
c
∣
d
∣
e
e
a|bb|cc|d|ee
a∣bb∣cc∣d∣ee,对于每个快都可以贡献答案
m
∗
n
−
n
m*n-n
m∗n−n
然后我们再看
a
b
a
b
abab
abab有两种方式可以变成
a
a
b
b
aabb
aabb,也就是隔着相等也会有重复的。而且
a
b
a
b
a
b
ababab
ababab时有
3
3
3种重复。也就是隔着相等的越多重复越多,而且每次多出来的都是和之前的重复,也就是隔着相等有
k
k
k个就有
C
k
2
C_{k}^2
Ck2个是重复的,减去之后就可以得出答案了
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
using namespace std;
inline LL read(){
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
LL n,m,ans,k;
char s[100005];
int main()
{
n=read();m=read();
scanf("%s",s+1);
ans=1;
for(LL i=2;i<=n;i++)
ans+=(s[i]!=s[i-1]);
ans*=n*m-n;k=1;
for(LL i=2;i<=n;i++)
if(k==1) k+=(s[i]!=s[i-1]);
else if(s[i]==s[i-2]) k++;
else{
ans-=k*(k-1)/2;
k=(s[i]!=s[i-1])+1;
}
ans-=k*(k-1)/2;
cout<<ans;
return 0;
}