몇 초 만에 알고리즘 이해 | 문자열 일치 알고리즘 분석 예: lurker, 최하위 3요소 문자열

 문자열 매칭 알고리즘은 실제 프로젝트에서 자주 접하게 되며, 대기업의 필기시험이나 면접에서도 흔히 출제되는 문제입니다. 이 알고리즘은 일반적으로 원본 문자열(문자열)과 하위 문자열(패턴)을 입력으로 사용하며 원본 문자열에서 하위 문자열이 처음 나타나는 위치를 반환해야 합니다. 예를 들어 원래 문자열이 "ABCDEFG"이고 하위 문자열이 "DEF"인 경우 알고리즘은 3을 반환합니다. 일반적인 알고리즘으로는 BF(Brute Force, brute force retrieval), RK(Robin-Karp, hash retrieval), KMP(교과서에서 가장 많이 사용되는 알고리즘), BM(Boyer Moore), Sunday 등이 있습니다.

01, 사례 분석: Lurker

문제 설명:

R국과 S국은 전쟁의 불길에 휩싸이고, 양측은 서로 럴커(간첩)를 보내 서로의 내부로 잠입해 기회를 노리는 행동을 기다린다. S국에 숨어 있던 R국의 스파이 꼬마 C는 많은 어려움을 겪은 끝에 마침내 S국의 군사 코드의 암호화 규칙을 알아냈습니다.

(1) S국 군대 내로 전송되는 원본정보는 암호화되어 인터넷을 통해 전송되며, 원본정보의 내용과 암호화된 내용은 대문자 'A' ~ 'Z'(공백 및 기타 문자 없이)로 구성된다. ) .

(2) S 국가는 각 문자에 해당하는 "비밀 단어"를 규정합니다. 암호화 과정은 원본 메시지의 모든 문자를 해당 "비밀 단어"로 바꾸는 것입니다.

(3) 각 문자는 고유한 "비밀 단어"에만 해당하고, 다른 문자는 다른 "비밀 단어"에 해당합니다. "비밀어"는 원문과 동일할 수 있습니다.

예를 들어 'A'의 비밀번호는 'A', 'B'의 비밀번호는 'C'(다른 문자와 비밀번호는 생략)로 지정하면 원본정보 "ABA"가 암호화된다. "ACA"로.

이제 Little C는 S 국가 네트워크에서 전송되는 암호화된 메시지와 내부 회선을 통해 해당 원본 메시지를 마스터했습니다. Little C는 이 정보를 사용하여 S 국가의 군사 코드를 해독하기를 희망합니다. Little C의 해독 과정은 다음과 같습니다. 원본 정보를 스캔하고, 원본 정보의 문자 X(모든 대문자를 나타냄)에 대해 암호화된 정보에서 해당 대문자 Y를 찾고, Y가 비밀번호에 있는 X의 비밀번호라고 생각합니다. 성격. 다음 상태 중 하나로 멈출 때까지 이 방법을 계속합니다.

(1) 모든 정보를 스캔하여 'A'부터 'Z'까지 26개의 문자가 모두 원본 정보에 나타나며 해당 '비밀어'를 획득했습니다.

(2) 모든 정보를 스캔하였으나, 원본 정보에 나타나지 않는 특정(또는 일부) 문자가 발견되었습니다.

(3) 스캔 과정에서 획득한 정보에 명백한 모순이나 오류(S국가 비밀번호의 암호화 규칙 위반)가 있음이 발견되었습니다. 예를 들어, "XYZ"라는 정보가 "ABA"로 번역되면 "다른 문자는 다른 비밀번호에 해당한다"는 규칙을 위반하는 것입니다.

Little C가 너무 바빠서 머리가 어질어질할 때, Country R의 본부는 방금 S Country에서 가로채온 또 다른 암호화된 메시지를 번역해 달라는 또 다른 전보를 보냈습니다. 이제 Little C를 도와주세요. 내부자가 얻은 정보를 통해 코드를 해독한 다음 해독된 코드를 사용하여 전보의 암호화된 정보를 번역하세요.

입력 형식:

총 3개의 라인이 있으며, 각 라인은 길이가 1부터 100까지의 문자열입니다.

첫 번째 줄은 Little C가 가지고 있는 암호화된 메시지입니다.

2행은 1행의 암호화된 정보에 해당하는 원본 정보입니다.

3행은 Country R의 본사에서 Little C에게 번역을 요구하는 암호화된 메시지입니다.

입력 데이터는 모든 문자열이 대문자 'A' ~ 'Z'로만 구성되고 첫 번째 줄의 길이가 두 번째 줄의 길이와 동일하도록 보장합니다.

출력 형식:

총 1줄.

코드 해독이 중단될 때 두 가지 상황 (2)와 (3)이 발생하면 Failed(첫 글자는 대문자, 나머지는 소문자)를 출력하고, 그렇지 않으면 암호화된 정보를 번역하기 위해 암호를 사용하여 얻은 원본 정보를 텔레그램이 출력됩니다.

입력 예 #1:

출력 샘플:

 입력 예:

출력 샘플:

 입력 예:

출력 샘플:

 

입력 및 출력 샘플 1 설명:

원본 메시지의 문자 'A'와 'B'는 동일한 비밀번호에 해당하며 Failed가 출력됩니다.

입력 및 출력 샘플 2 설명:

원본 메시지에는 문자 'Z'가 나타나지 않으며 Failed가 출력됩니다.

아이디어:

(1) A~Z가 모두 존재해야 하며, 그렇지 않으면 Failed가 출력됩니다.

(2) 암호문의 각 문자는 여러 문자로 사용될 수 없으며, 그렇지 않으면 Failed가 출력됩니다.

참조 절차:

#include<iostream>
#include<cstring>
using namespace std;
char map[26];
int main()
{
string secret,original,translation;
int len1,len3;
int i,j;
cin>>secret>>original>>translation; ;//输人密文、原文、要翻译的文字
len1=secret.length() ;  //计算密文长度
len3=translation.length(); //计算要翻译的文字长度
if(len1<26)  //若密文长度小于 26 个字母的长度,则不合要求,输出 Eailed,终止程序
}
{
cout<<"Failed"<<endl;
return 0;
}
for(i=0;i<lenl;i++)
{
for(j=0;j<i;j++)
if(original[i]==original[jl&&secret[il!=secret[j]) //若原文中有相同字母,但密文中对应字母不相同,则不合要求,输出 Eailed,终止
//程序
{
cout<<"Failed"<<endl;
return 0;
}
map[secret[il-'A']=original[i];   //存储密文对应的原文 
}
for(i=0;i<len3;i++)  //输出翻译后的文字
cout<<map[translation[i]-'A'];
cout<<end1;
return 0;    
}

02,분석 예: 가장 낮은 3개 요소 문자열

문제 설명:

삼항 문자열이 주어지면(문자열은 문자 '0', '1' 및 '2'로만 구성됨).

두 개의 인접한(연속) 문자 '0'과 '1'(예: '01'을 '10'으로 바꾸거나 그 반대로 대체) 또는 두 개의 동일한 문자를 바꿀 수 있습니다. 인접한(연속) 문자 "1"과 "2"( 즉, "12"를 "21"로 바꾸거나 그 반대로 바꿉니다. 예를 들어 문자열 "010210"의 경우 다음 단계를 수행할 수 있습니다.

“010210”→→ “100210”;

“010210” →→ “001210”;

“010210” →→ “010120”;

“010210” →→ “010201”。

예를 들어 문자열 "010210"의 경우 다음 작업을 수행할 수 있습니다. "02"를 "20"으로 또는 그 반대로 변환할 수 없습니다. 주어진 문자열로는 위에 설명된 작업 이외의 작업을 수행할 수 없습니다.

당신의 임무는 이러한 교환을 여러 번(아마도 0) 사용하여 가능한 가장 작은(사전식) 문자열을 얻는 것입니다.

위치 i가 있는 경우(1≤i≤|a|, 여기서 |s|는 문자열 "ss"의 길이임) 문자열 "aa"는 문자열 "bb"보다 사전순으로 작습니다(문자열 " ; aa"와 "bb"는 동일한 길이를 가짐), 각 j

입력하다:

입력의 첫 번째 줄에는 '0', '1', '2'로만 구성된 문자열 "s"가 포함되어 있으며 길이는 1부터 105( 포함 105).

산출:

문자열을 인쇄합니다. 위에서 설명한 스왑을 사용하여 얻을 수 있는 (사전순) 문자열의 최소 수(0일 수도 있음)입니다.

입력 예:

100210

출력 샘플:

001120

입력 예:

11222121

출력 샘플:

11112222

입력 예:

20

출력 샘플:

20

질문 의미: 0, 1, 2만 있는 숫자열이 주어지면 0과 1은 서로 바뀔 수 있고, 1과 2도 서로 바뀔 수 있습니다. 교환 후 가장 작은 값을 찾으세요.

아이디어: 1이 어디에 있든 항상 2 이전에 대체될 수 있지만 0은 2 이전에 대체될 수 없으므로 먼저 처음 2 이전에 0의 개수를 세어 출력한 다음 전체 문자열에서 1의 개수를 세세요. , 출력; 마지막으로 처음 2 이후의 모든 숫자에서 1을 제거하고 출력합니다.

참조 절차:

#include<iostream>
#include<cstdio>
#include<cstring>
# include< cmath>
#include<algorithm>
#include<string>
# include<cstdlib>
# include<queue>
# include< set>
# include<map>
#include<stack>
#include<ctime>
#include<vector>
#define INF Ox3f3f3f3f
# define PI acos(-1.0)
#define N 1001
#define MOD 10007
#define E 1e-6
# define LL long long
using namespace std;
int main()
{
string str;
cin>>str;
LL len=str.length() ;
LI num 1=0;
bool flag=true;
for(LL i=0;i<len;i++)
if(str[il=='1')num 1++;
if(str[i]=='1' str[i]=='2')
flag=false;
LL pos;
LI num 0=0;
for(LL i=0;i<len;i++)
f(str[i]=='0')
num 0++;
if(str[i]=='2')
pos=i;
break;
if(flag)
cout<<str<<endl;
return 0;
}
while(num 0--)
cout<<'0';
while(num 1--)
cout<<'1';
for(LL i=pos;i<len;i++)
{
if(str[il=='1')
continue;
else
cout<<str[i];
}
cout<<endl;
return 0;
}

추천

출처blog.csdn.net/qq_41640218/article/details/133738157