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;
    }
    
    转载需注明出处。
  • 相关阅读:
    Nginx 部署多个 web 项目(虚拟主机)
    Nginx 配置文件
    Linux 安装 nginx
    Linux 安装 tomcat
    Linux 安装 Mysql 5.7.23
    Linux 安装 jdk8
    Linux 安装 lrzsz,使用 rz、sz 上传下载文件
    springMVC 拦截器
    spring 事务
    基于Aspectj 注解实现 spring AOP
  • 原文地址:https://www.cnblogs.com/jz929/p/11817543.html
Copyright © 2011-2022 走看看