zoukankan      html  css  js  c++  java
  • [AtCoder] AT4379 [AGC027E] ABBreviate

    Description

    (Link)

    Solution

    (G(S)=sumlimits_{i=1}^{|S|}(S_i-'a'+1)pmod{3})。那么经过若干次变换,(G(S))始终不会改变。

    注意到一个字符串(S)能变换成(T)(S eq{T})),当且仅当(S)能被划分成若干段,满足每一段的(G(S'))都等于(G(T_i))(S)中至少有两个连续字符相同,且若还剩下最后一段没有匹配,则(G(S_{lst})=0)。(因为(G(S)=G(T))

    举个例子:设(S=aabbabaabaaabab)(T=abba),那么(S)会被划分为(a|abb|abaa|baa|abab)。这是满足的,因为(G(abab)=0)

    因此,我们设(dp[i])表示在(S)中,以(S_i)为后缀的答案。

    最开始先把形如(ababababababa)的判掉。

    再设一个(nxt[i][0/1])表示(dp[i])由哪里更新而来(如由(dp[nxt[i][0]])再向前面添一个(a)得来)

    那么转移方程即为(dp[i] = dp[nxt[i][0]] + dp[nxt[i][1]] + (s == 0)),其中(s)表示(G(S_{isim{n}}))

    解释:可以由(dp[nxt[i][0]])再向前面添一个(a)得来,也可以由(dp[nxt[i][1]])再向前面添一个(b)得来,还可以直接作为一个后缀(这要满足(G(S_{isim{n}})=0)

    (nxt)数组的更新如下:

    (nxt[i][0])为例:如果(S_i=a),那么(nxt[i][0]=i+1);如果(S_i=S_{i+1}=b),那么(nxt[i][0]=i+2);((bb ightarrow{a})),否则(nxt[i][0]=nxt[i+2][0])。例如,在(S=babba,i=1)时,计算可得(nxt[i][0]=5)。发现(babb)恰好可以转化为(a)

    答案为(dp[1])。当然,要记得最后减掉(s==0),因为整个串不可能单独做一个后缀。

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int mod = 1e9 + 7;
    
    int n, s, dp[100005], nxt[100005][2];
    
    char ch[100005];
    
    int read()
    {
    	int x = 0, fl = 1; char ch = getchar();
    	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
    	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
    	return x * fl;
    }
    
    int main()
    {
    	scanf("%s", ch + 1);
    	n = strlen(ch + 1);
    	int ok = 0;
    	for (int i = 1; i <= n - 1; i ++ )
    		if (ch[i] == ch[i + 1])
    			ok = 1;
    	if (!ok)
    	{
    		puts("1");
    		return 0;
    	}
    	dp[n + 1] = 1;
    	nxt[n + 1][0] = nxt[n + 1][1] = n + 2;
    	nxt[n + 2][0] = nxt[n + 2][1] = n + 2;
    	for (int i = n; i >= 1; i -- )
    	{
    		s = (s + ((ch[i] == 'a') ? 1 : 2)) % 3;
    		if (ch[i] == 'a') nxt[i][0] = i + 1;
    		else if (ch[i + 1] == 'b') nxt[i][0] = i + 2;
    		else nxt[i][0] = nxt[i + 2][0];
    		if (ch[i] == 'b') nxt[i][1] = i + 1;
    		else if (ch[i + 1] == 'a') nxt[i][1] = i + 2;
    		else nxt[i][1] = nxt[i + 2][1];
    		dp[i] = (dp[nxt[i][0]] + dp[nxt[i][1]] + (s == 0)) % mod;
    	}
    	printf("%d
    ", (dp[1] - (s == 0) + mod) % mod);
    	return 0;
    }
    
  • 相关阅读:
    (转载)gethostbyname() 用域名或主机名获取IP地址
    (转载)Linux网络编程inet_aton和inet_network和inet_addr三者比较
    (转载)Linux网络编程inet_pton与inet_ntop
    (转载)获取以太网卡的MAC地址
    (转载)Linux网络编程使用gethostbyaddr,通过ip地址,得到该ip地址的主机的信息
    (转载)Linux网络编程inet_ntoa问题记录
    Linux中pthread_detach()线程注意
    regexpfield tcl tk
    Iwidgets checkbox
    iwidgets hyperhelp tcl tk
  • 原文地址:https://www.cnblogs.com/andysj/p/14465898.html
Copyright © 2011-2022 走看看