公式
C - 1122 String 解説
by
C - 1122 String 解説
by
mechanicalpenciI
与えられた文字列が 1122 文字列の \(3\) つの条件をみたしているかそれぞれ確認すれば良いです。
\(3\) つめの条件は、\(1,2\) つめの条件がみたされている仮定のもとで、以下の \(2\) 通りなどのようにも言い換えられるため、直接確認する代わりにそのことを確認しても良いです。
なお、\(S_i\) で \(S\) の \(i\) 文字目を表すものとします。
- \(S_1,S_3,\ldots, S_{|S|-1}\) はすべて異なる。
- \(S\) の各文字 \(S_i\) について、\(S\) の中にその文字と一致するものはちょうど \(2\) つ存在する。
すなわち、\(1\) 以上 \(|S|\) 以下の任意の整数 \(i\) について、\(S_i=S_j\) となる \(j\) \((1\leq j\leq |S|)\) はちょうど \(2\) つ存在する。
計算量は元の方法では \(O(\lvert S\rvert+C)\) です。ここで、 \(C\) は \(S\) に使われる候補となる文字の種類数であり、今回の問題では \(C=26\) となります。言い換えた後の条件の確認には、ナイーブに実装したとき \(\Theta(\lvert S\rvert^2)\) の計算量がかかりますが、今回は \(\lvert S\rvert\leq 100\) のため時間的に問題ありません。よって、いずれの方法でも十分高速に判定を行うことができ、この問題を解くことができました。
c++ による実装例:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
string s;
int cnt[26]={};
bool flag=true;
cin>>s;
n=s.size();
if(n%2==1)flag=false;
if(flag){
for(int i=0;i<(n/2);i++){
if(s[2*i]!=s[2*i+1])flag=false;
}
}
if(flag){
for(int i=0;i<n;i++){
cnt[s[i]-'a']++;
}
for(int i=0;i<26;i++){
if((cnt[i]!=0)&&(cnt[i]!=2))flag=false;
}
}
if(flag)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}
Python による実装例:
s=input()
flag=True
if len(s)%2==1:
flag=False
if flag:
for i in range(len(s)//2):
if s[2*i]!=s[2*i+1]:
flag=False
cnt=[0 for i in range(26)]
if flag:
for i in range(len(s)):
cnt[ord(s[i])-ord('a')]+=1
for i in range(26):
if cnt[i]!=0 and cnt[i]!=2:
flag=False
if flag:
print("Yes")
else:
print("No")
投稿日時:
最終更新:
