最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(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】題解的評論 (共 條)

分享到微博請遵守國家法律
从化市| 海安县| 宁海县| 福泉市| 浮山县| 清水县| 云南省| 武冈市| 梁山县| 萝北县| 武安市| 伊金霍洛旗| 昌图县| 云霄县| 太原市| 乌兰浩特市| 泌阳县| 敖汉旗| 原平市| 淳安县| 正宁县| 平度市| 康平县| 中阳县| 颍上县| 叶城县| 顺昌县| 铜川市| 江源县| 涞水县| 金塔县| 呼伦贝尔市| 龙游县| 金川县| 科尔| 桦甸市| 新宾| 天长市| 仙居县| 永德县| 前郭尔|