zoukankan      html  css  js  c++  java
  • jzoj 4673. 【NOIP2016提高A组模拟7.20】LCS again

    Description

    现在有一个长度为n的串S,其中每一个字母都是前m个小写字母
    计算有多少个不同的长度为n的T(其中T也是由前m个小写字母组成),并且S与T的LCS为n-1
    LCS就是同时存在于S和T的最长子序列

    Input

    第一行包含两个整数n和m表示S的长度和前m个小写字母
    第二行是串S

    Output

    只要输出存在的T的数量

    Sample Input

    输入1:
    3 3
    aaa

    输入2:
    3 3
    aab

    输入3:
    1 2
    a

    输入4:
    10 9
    abacadefgh

    Sample Output

    输出1:
    6

    输出2:
    11

    输出3:
    1

    输出3:
    789

    样例解释
    第一个样例有6个可能的串T:aab,aac,aba,aca,baa,caa
    第二个样例有11个可能的串T
    Aaa,aac,aba,abb,abc,aca,acb,baa,bab,caa,cab
    第三个样例只有b

    Data Constraint

    对于20%,n<=100
    对于30%,n<=1000
    对于40%,n<=10000
    对于100%,n<=100000

    Solution

    这题我是问人+看题解才懂了的。

    找规律。。。

    感觉这样例出得很善良。。。
    我们先看样例1:
    3 3
    aaa
    我们发现将任意一个取出+(换字母)+插入都会有重。
    我们发现,答案是:1 * n * (m-1)=3 * 2=6
    发现1:一段相同的字母的贡献其实就是一个字母的贡献
    再看看样例2:
    3 3
    aab
    我们发现将a插入b后和b插入a前是重了的。
    怎么办呢?
    经过搞基似的严谨的推论,我们发现:
    当a=x(符合条件的小写字母),b=y(同上)时
    ab…ab(共k个ab)的贡献就是:(k-1)*k/2
    按照此推论搞搞样例3,发现可过。
    于是,可过。

    Code

    #include<cstdio>
    #define ll long long
    using namespace std;
    int n,m; ll ans,k;
    char s[100010];
    int main() 
    {
    //	freopen("LCS again.in","r",stdin);
    //	freopen("LCS again.out","w",stdout);
    	scanf("%d%d%s",&n,&m,s+1);
    	for (int i=1;i<=n;i++)
    		if (s[i]!=s[i+1]) ans+=n*(m-1);
    //	printf("%lld
    ",ans);
    	k=1;
    	for (int i=2;i<=n;i++)
    	{
    		if (k==1) {if (s[i]!=s[i-1]) k++;}
    		else if (s[i]==s[i-2]) k++;
    		else ans-=k*(k-1)/2,k=(s[i]==s[i-1]) ? 1:2;
    	}
    	ans-=k*(k-1)/2;
    	printf("%lld",ans);
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    redis-hash
    redis-list操作
    bootstrap之消息提示
    jQuery水平下拉菜单实现
    JavaScript的Date对象
    积水问题
    Queue的push和front操作
    Stack的pop和push操作
    .py文件不能设置默认打开程序 win10
    Anaconda的安装
  • 原文地址:https://www.cnblogs.com/jz929/p/11817543.html
Copyright © 2011-2022 走看看