国产精品天干天干,亚洲毛片在线,日韩gay小鲜肉啪啪18禁,女同Gay自慰喷水

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Luogu_CF578D 【LCS Again】題解

2019-12-28 18:31 作者:hnyqwq  | 我要投稿

1.【題目鏈接】https://www.luogu.com.cn/problem/CF578D


題目描述


You are given a string?S?of length?n?with each character being one of the first?m?lowercase English letters.


Calculate how many different strings?T?of length?n?composed from the first?m?lowercase English letters exist such that the length of LCS (longest common subsequence) between?S?and?T?is?n-1?.


Recall that LCS of two strings?S?and?T?is the longest string?C?such that?C?both in?S?and?T?as a subsequence.


輸入格式


The first line contains two numbers?nn?and?mm?denoting the length of string?SS?and number of first English lowercase characters forming the character set for strings (?1<=n<=100000?,?2<=m<=26?).


The second line contains string?S?.


輸出格式


Print the only line containing the answer.


題意翻譯


題目描述


給定一個長度為n,前m個字母都是小寫字母的字符串S. 試計算有多少個長度為n,前m個字母為小寫字母且與字符串S的LCS(最長上升子序列,Longest Common Subsequence)長度為n-1的字符串T 注:字符串S和T的LCS是指一個在S和T中都能找得到的最長子序列.


輸入輸出格式


輸入格式:


第一行包括兩個數(shù)字n和m,第二行是給定的字符串S.


感謝@mMmP 提供的翻譯


輸入輸出樣例


輸入 #1復(fù)制

3 3?

aaa

輸出 #1復(fù)制

6

輸入 #2復(fù)制

3 3?

aab

輸出 #2復(fù)制

11

輸入 #3復(fù)制

1 2?

a

輸出 #3復(fù)制

1

輸入 #4復(fù)制

10 9?

abacadefgh

輸出 #4復(fù)制

789

說明/提示


For the first sample, the?66?possible strings?TT?are: aab, aac, aba, aca, baa, caa.


For the second sample, the?1111?possible strings?TT?are: aaa, aac, aba, abb, abc, aca, acb, baa, bab, caa, cab.


For the third sample, the only possible string?TT?is b.


2.思路


題解給了一個不用DP的機智做法。


我們現(xiàn)在采取的策略是,用算重方案數(shù)減去重復(fù)的方案數(shù)。 我們考慮三個條件:


1、取出哪個字符


2、放在哪個位置


3、放置什么字符


首先,很容易知道每個字符在原位置上就有m-1種方案,那么初始方案就有n*(m-1)種。


然后我們考慮取出串中的一個字符,然后再把這個字符放入字符串中,這樣顯然會有大量重復(fù),我們發(fā)現(xiàn)大部分的重復(fù)情況都是s[i]=s[i-1]這樣,由相鄰且相同的串組成的很多歌塊,每個塊中都是相同的字符,這樣取出來再填進去,同一個塊中的放置后情況完全一樣。例如aaabaccc,按照相鄰且相同來分塊, aaa|b|a|ccc,一共四個塊,例如要在第一個塊中取出一個那么就變成了aa|b|a|ccc,然后再把a插入,可以發(fā)現(xiàn)在第一個塊中取任意一個的放置情況都是一樣的,所以可以把一個塊中值拿出一個點來計算,這樣就不會被相鄰且相同的字符影響。然后我們考慮,取出的這些字符放置成什么字符。如上個例子,把取出的a放在b右邊,可以變成aabaaccc,aabbaccc,aabcaccc……假如把a放在b的右邊可以變成aabbaccc,aacbaccc……我們可以發(fā)現(xiàn)算多了一個,而這種情況會有n次,就是說從一個塊中取出一個數(shù)再放到任意位置只能放m-1種字符。

scanf("%d%d",&n,&m);scanf("%s",s+1);
? ?ans=n*(m-1);
? ?fo(i,2,n)if(s[i]!=s[i-1])ans+=n*(m-1);

然而還會算重?。。。?!


比如說abababab這樣的字符串,例如把第3個a放到后面變成abbaabab,但是把第4個b放到前面也可以變成abbaabab,這樣也會算重。這種字符串中每個字符會與前面任意一個字符算重一次,所以答案還要減去k*(k-1)/2(k是字符串的大小,因為第一個字符前面有0個字符,第二個字符前面有1個……第k個字符前面有k-1個,總和=(首項+末項)?項數(shù)/2=(0+k-1)?k/2=k *(k-1)/2

k=1;
? ?fo(i,2,n){
? ? ? ?if(k==1){if(s[i]!=s[i-1])k++;else continue;}
? ? ? ?else{
? ? ? ? ? ?if(s[i]==s[i-2])k++;
? ? ? ? ? ?else{
? ? ? ? ? ? ? ?ans-=(k-1)*k/2;k=1;
? ? ? ? ? ? ? ?if(s[i]!=s[i-1])k=2;
? ? ? ? ? ?} ? ??
? ? ? ?}
? ?}
? ?ans-=(k-1)*k/2;

3.Code

//Happynewyear 2019/1/23 20:22
#include<bits/stdc++.h> ? ? ? ? //萬能頭文件
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100007;
int i,j,l,t,n,m;
long long ans,k;
char s[maxn];
int main(){
? ?scanf("%d%d",&n,&m);scanf("%s",s+1); ? //輸入
? ?ans=n*(m-1);
? ?fo(i,2,n)if(s[i]!=s[i-1])ans+=n*(m-1);k=1;
? ?fo(i,2,n){
? ? ? ?if(k==1){if(s[i]!=s[i-1])k++;else continue;}
? ? ? ?else{
? ? ? ? ? ?if(s[i]==s[i-2])k++;
? ? ? ? ? ?else{
? ? ? ? ? ? ? ?ans-=(k-1)*k/2;k=1;
? ? ? ? ? ? ? ?if(s[i]!=s[i-1])k=2;
? ? ? ? ? ?} ? ?
? ? ? ?}
? ?}
? ?ans-=(k-1)*k/2;
? ?printf("%lld\n",ans); ? //輸出
}

提交記錄 in 2019-10-10



Luogu_CF578D 【LCS Again】題解的評論 (共 條)

分享到微博請遵守國家法律
华宁县| 高碑店市| 深圳市| 乌兰浩特市| 洛宁县| 蚌埠市| 承德县| 武夷山市| 开鲁县| 明水县| 安新县| 巢湖市| 伊金霍洛旗| 诸城市| 和林格尔县| 沙洋县| 仪征市| 杂多县| 建湖县| 泾阳县| 金溪县| 保亭| 汤阴县| 壶关县| 鸡泽县| 阜康市| 鲁山县| 镇平县| 沙河市| 清水县| 宣城市| 凤庆县| 霍州市| 白水县| 双城市| 徐闻县| 山阳县| 临江市| 铜川市| 维西| 屯留县|