zoukankan      html  css  js  c++  java
  • HackerRank beautiful string

    问题

    https://vjudge.net/problem/HackerRank-beautiful-string

    给一个字符串S,可以任意取走S中的两个字符从而得到另外一个字符串P,求有多少种不同的P

    (left|S ight|le10^6)

    题解

    想到组合数
    将连续的相同的字符分为1组,如字符串“aaabbbbaccca
    则可以选两组中的两个字母或一组中的两个字母
    计算出连续的组数设为x
    计算出长度大于等于2的组数设为y
    [ans = left( egin{array}{l}x\2end{array} ight) + y]
    时间复杂度$O(n)$

    这样当然WA了

    因为没有考虑是否存在两种移除(单个)字母的方法使结果相同。:(

    以下考虑粗体的字母,且每种情况中xxxxx都不会造成前面情况

    1.容易得aba,移除前两个字母和移除后两个字母效果相同。

    2.容易得abc,(a$ e$bb$ e$ca$ e$c),任意移除两个都不会得到相同的P

    3.容易得abxxxxxca$ e$b,|xxxxx|>0)和axxxxxbcb$ e$c|xxxxx|>0),任意移除两个都不会得到相同的P

    4.容易得axxxxxbxxxxxc,无论abc相同还是不同,任意移除两个都不会得到相同的P

    5.字符串A $ e$ B,那么xxxxxAxxxxx$ e$xxxxxBxxxxx

    所以移除单个字母只会因为第一种情况造成重复

     

    多个aba重复可以减去后面的情况,因此我们可以直接减去aba出现的次数

    AC代码

    #include <bits/stdc++.h>
    #define REP(i,x,y) for(register int i=x; i<y; i++)
    #ifdef LOCAL
    #define DBG(x,...) printf(x, ##__VA_ARGS__)
    #else
    #define DBG(x,...) (void)(0)
    #endif
    using namespace std;
    char S[1000007];
    inline void gs(int &p) {
    	p=0;
    	while((S[p++]=getchar())>' ');
    	S[--p]=0;
    }
    int main()
    {
    	int r;gs(r);
    	long long x=0,y=0;
    	char l=0,cn=1;
    	REP(i,0,r) {
    		if(S[i]!=l) {
    			x++;
    			if(cn>=2) y++;
    			cn=1;
    		} else {
    			cn++;
    		}
    		l=S[i];
    	}
    	if(cn>=2) y++,cn=1;
    //	DBG("%s %d %lld %lld
    ", S, r, x, y);
    	long long ans= (x&1) ? (x-1)/2*x+y : x/2*(x-1)+y;
    //	long long t=0;
    	r--;
    	REP(i,1,r) {
    		if(S[i-1]==S[i+1] && S[i-1]!=S[i]) ans--;
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    [算法练习]序列最大和
    [算法练习]最长公共子序列
    [算法练习]最长公共子串(LCS)
    [算法练习] 把字符串转换成整数
    [算法练习] 反转链表
    [算法练习] 正整数数制转换
    自己调用NTDLL函数
    [经典算法] 排列组合-N元素集合的所有子集(二)
    [经典算法] 排列组合-N元素集合的所有子集(一)
    【机器学习】主成分分析法 PCA (I)
  • 原文地址:https://www.cnblogs.com/sahdsg/p/10357560.html
Copyright © 2011-2022 走看看