Codeforces 1379A题解

A. Acacius and String
time limit per test1 second
memory limit per test512 megabytes
inputstandard input
outputstandard output
Acacius is studying strings theory. Today he came with the following problem.

You are given a string s of length n consisting of lowercase English letters and question marks. It is possible to replace question marks with lowercase English letters in such a way that a string “abacaba” occurs as a substring in a resulting string exactly once?

Each question mark should be replaced with exactly one lowercase English letter. For example, string “a?b?c” can be transformed into strings “aabbc” and “azbzc”, but can’t be transformed into strings “aabc”, “a?bbc” and “babbc”.

Occurrence of a string t of length m in the string s of length n as a substring is a index i (1≤i≤n−m+1) such that string s[i…i+m−1] consisting of m consecutive symbols of s starting from i-th equals to string t. For example string “ababa” has two occurrences of a string “aba” as a substring with i=1 and i=3, but there are no occurrences of a string “aba” in the string “acba” as a substring.

Please help Acacius to check if it is possible to replace all question marks with lowercase English letters in such a way that a string “abacaba” occurs as a substring in a resulting string exactly once.

Input
First line of input contains an integer T (1≤T≤5000), number of test cases. T pairs of lines with test case descriptions follow.

The first line of a test case description contains a single integer n (7≤n≤50), length of a string s.

The second line of a test case description contains string s of length n consisting of lowercase English letters and question marks.

Output
For each test case output an answer for it.

In case if there is no way to replace question marks in string s with a lowercase English letters in such a way that there is exactly one occurrence of a string “abacaba” in the resulting string as a substring output “No”.

Otherwise output “Yes” and in the next line output a resulting string consisting of n lowercase English letters. If there are multiple possible strings, output any.

You may print every letter in “Yes” and “No” in any case you want (so, for example, the strings yEs, yes, Yes, and YES will all be recognized as positive answer).

Example
inputCopy
6
7
abacaba
7
???
11
aba?abacaba
11
abacaba?aba
15
asdf???f???qwer
11
abacabacaba
outputCopy
Yes
abacaba
Yes
abacaba
Yes
abadabacaba
Yes
abacabadaba
No
No
Note
In first example there is exactly one occurrence of a string “abacaba” in the string “abacaba” as a substring.

In second example seven question marks can be replaced with any seven lowercase English letters and with “abacaba” in particular.

In sixth example there are two occurrences of a string “abacaba” as a substring.
题解
首先,我们先要检查当前这个已经输入的长度为n的字符串,有没有唯一的子串“abacaba"
引理 1. 这个检查算法的时间复杂度为O(n) (一遍循环直接过)
证明:我们可以尝试取字符串s里所有的位置i并且检查它是否是子串”abacaba"的起点。这个检查可以在O(1)范围内实现(就是s.substr(i,7)和“abacaba”比较一下),所以总时间复杂度为n⋅O(1)=O(n)
为了解决问题我们需要迭代所有的位置i并且检查是否存在一个合法的字符串使得从位置i算起有唯一一个子串“abacaba"。字符串s有唯一一个子串”abacaba"是当且仅当以下两个规则满足时才成立:
1)i是s中子串“abacaba"的起点
2)在字符串s中,没有其他起点j(i≠j)也是"abacaba"的起点)

第一条规则可以直接去检查。当且仅当对于所有的j∈[0;6] si+j=tj or si+j=′?′时,i才是合法起点。简单来说就是从i开始算起,要跟”abacaba“一一对应,如果不能直接对应,要判断此时s[i+j]处是不是‘?’,如果不是的话就不能成立。
对于第二种情况需要下面的引理
引理 2. s中的问号可以用一个小写因为字母替换使得新的"abacaba"出现。
证明:
假设我们将所有问号用’z‘替换,因为“abacaba”里没有z,所以这样的替换不可能替换出新的“abacaba”
所以在构造出第一个“abacaba"之后,就可以直接构造剩余部分了。
这整套算法时间复杂度为O(n2)

代码(官方AC)

#include <bits/stdc++.h>

using ll = long long;
using ld = long double;
using ull = unsigned long long;

using namespace std;

const string T = "abacaba";

int count(const string& s) {
    int cnt = 0;
    for (int i = 0; i < (int)s.size(); ++i) {
        if (s.substr(i, T.size()) == T) {
            ++cnt;
        }
    }

    return cnt;
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t;
    cin >> t;
    for (int tt = 1; tt <= t; ++tt) {
        int n;
        cin >> n;
        string s;
        cin >> s;
        bool F = false;

        for (int i = 0; i + T.size() <= n; ++i) {
            string ss = s;
            bool ok = true;
            for (int j = 0; j < T.size(); j++) {
                if (ss[i + j] != '?' && ss[i + j] != T[j]) {
                    ok = false;
                    break;
                }
                ss[i + j] = T[j];
            }
            if (ok && count(ss) == 1) {
                for (int j = 0; j < n; j++) {
                    if (ss[j] == '?') {
                        ss[j] = 'd';
                    }
                }
                F = true;
                cout << "Yes\n";
                cout << ss << "\n";
                break;
            }
        }
        if (!F) {
            cout << "No\n";
        }
    }

    return 0;
}

我自己写的(失败了,气死我了wrong answer Jury found answer, participant not (test case 179)每次都是这个哈批错误,比赛的时候我的思路跟教程是一样的不知道为啥这里会错)

#include<bits/stdc++.h>
using namespace std;
int main(){
	int t,n,tot;
	string s,s1,s2;
	string ans="abacaba";
	bool ok;
	cin>>t;
	while (t--){
		  tot=0; ok=false;
		  cin>>n;
		  cin>>s;
		  for (int i=0; i<n; i++){
                 s1=s.substr(i,7);
		  	     if (s1=="abacaba")
		  	        tot++;
		  }
		  if (tot>1){
		  	 cout<<"No"<<endl;
		  	 continue;
		  }
		  if (tot==1){
		  	 cout<<"Yes"<<endl;
		  	 for (int i=0; i<n; i++)
		  	     if (s[i]=='?')
		  	        s[i]='z';
		  	 cout<<s<<endl;
		  	 continue;
		  }
		  int i=0;  tot=0;
		  bool f=true;
		  while (i<n){
		  	  f=true;
		  	  if (not(ok)){
		  	  	 for (int j=i; j<i+7; j++){
		  	  	 	 if (s[j]!=ans[j-i])
		  	           if (s[j]!='?'){
		  	           	    f=false;
		  	             	break;
					   }
				}
				if (f && !ok && tot<1){
					for (int j=i; j<i+7; j++){
		  	           if (s[j]=='?')
		  	               s[j]=ans[j-i];
			        }
			        ok=true;
			     	i=i+6;
				}
			  }
			  else{
			  	  break;
			  }
			  i++;
		  }
		  if (not(ok))
		     cout<<"No"<<endl;
		  else{
		  for (int i=0; i<n; i++)
		      if (s[i]=='?')
		         s[i]='z';
		  	 tot=0;
		  	for (int i=0; i<n; i++){
                 s1=s.substr(i,7);
		  	     if (s1=="abacaba")
		  	        tot++;
		    }
		  if (tot>1){
		  	 cout<<"No"<<endl;
		  	 continue;
		  }
		  	 cout<<"Yes"<<endl;
		  	 cout<<s<<endl;
		  }
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值