E - Strings of Impurity (AtCoder Beginner Contest 138)

E - Strings of Impurity 

题目链接:https://atcoder.jp/contests/abc138/tasks/abc138_e

Problem Statement

Given are two strings s and t consisting of lowercase English letters. Determine if there exists an integer i satisfying the following condition, and find the minimum such i if it exists.

  • Let s′ be the concatenation of 10100(格式问题,10的100次) copies of s. t is a subsequence of the string s′1s′2…s′i (the first i characters in s′).

Notes

  • A subsequence of a string a is a string obtained by deleting zero or more characters from aand concatenating the remaining characters without changing the relative order. For example, the subsequences of contest include net, c, and contest.

Constraints

  • 1≤|s|≤105

  • 1≤|t|≤105
  • s and t consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

s t

Output

If there exists an integer i satisfying the following condition, print the minimum such i; otherwise, print -1.

Sample Input 1 

contest son

Sample Output 1 

10

t= son is a subsequence of the string contestcon (the first 10 characters in s′=contestcontestcontest...), so i=10 satisfies the condition.

On the other hand, t is not a subsequence of the string contestco (the first 9 characters in s′), so i=9 does not satisfy the condition.

Similarly, any integer less than 9 does not satisfy the condition, either. Thus, the minimum integer i satisfying the condition is 10.

Sample Input 2 

contest programming

Sample Output 2 

-1

t= programming is not a substring of s′= contestcontestcontest.... Thus, there is no integer i satisfying the condition.

Sample Input 3 

contest sentence

Sample Output 3 

33

 

Note that the answer may not fit into a 32-bit integer type, though we cannot put such a case here.

 

 

题目意思:

给你两个字符串s和t,s可以重复10的100次,问是否存在一个子序列等于t,存在的话输出t最后一位字符在s中的位置,不存在的话,输出-1

解题思路:

打表,map(一个数组)记录s上26个字母距离该位置wz最近的位置x,答案(ans)加上x-wz+1;如果当前匹配的位置为0(s的开头),且没有匹配的字符(即map[ t[i]-'a' ][wz] == -1),说明重复的s中不存在和t匹配的子序列,即输出-1,如果当前位置wz不是开头的话,则到下一段s中找,直到找完或不满足条件。(言语表达不好,下面请看代码)ヾ(´▽`;)ゝ

先放个思路相似,但是TLE的代码  (ó﹏ò。)难受:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string> 
using namespace std;
int main(){
	string s,t;
	int f = 0;
	cin>>s>>t;
	long long ans = 0;
	string::iterator wz = s.begin();
	int flag = 0; //表示是否存在与t匹配的子序列
	for(int i = 0; i < t.length(); i++){
		if(f == 0 && find(wz,s.end(),t[i])==s.end()){ //如果在开头,也没找到t[i]的话,说明不存在
			flag = 1;
			break;
		}
		else{
			if(find(wz,s.end(),t[i])!=s.end()){ //如果找到了
				ans+=(find(wz,s.end(),t[i]) - wz+1); //答案加上
				wz = find(wz,s.end(),t[i])+1; //改变当前位置到匹配的字符后一位
				f = 1;
			}
			else{ //没找到,但是当前位置不在开头
				ans+=s.end()-wz; //进入下一段s,答案先加上
				f = 0;
				wz = s.begin(); //当前位置变为下一段开头
				i--; //因为没匹配到,所以还是匹配这个字符,i不能++
			}
		}
	}
	if(flag == 1)
		printf("-1\n");
	else{
		printf("%lld\n",ans);
	}
	return 0;
}

接下来是AC代码  (•̀∀•́)棒:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string> 
using namespace std;
const int M = 1e5 + 50;
int map[26][M];
int main(){
	string s,t;
	int f = 0;
	cin>>s>>t;
	long long ans = 0;
   //1.打表
	for(int i = 0; i < 26; i++)map[i][s.length()] = -1; //初始化,-1表示从s.length向右找不到(i+'a')
	for(int i = s.length()-1 ; i >=0; i-- ){
		for(int j = 0; j < 26; j++){
			map[j][i] = map[j][i+1]; //记录从i开始向右最近的( 'a'+j )在哪个位置;
		}
		map[s[i]-'a'][i] = i; //第i位开始向右最近的s[i]的位置在i
	}
 
	int flag = 0; //是否存在
	int wz = 0; //当前位置
	for(int i = 0; i < t.length(); i++){
		if(wz == 0 && map[t[i]-'a'][wz] == -1){//如果在开头,也没找到t[i]的话,说明不存在
			flag = 1;
			break;
		}
		else{
			if( map[t[i]-'a'][wz] != -1 ){//找到t[i]的话
				ans+=map[t[i]-'a'][wz]-wz+1;//答案加到这个位置
				wz = map[t[i]-'a'][wz]+1;//改变当前位置到匹配到的下一位
			}
			else{//如果没找到,但是当前位置不在开头,进入下一段s
				ans+=s.length()-wz;//先将位置变到该段s最后
				wz = 0;//当前位置变为下一段s的开始
				i--;//因为没匹配到t[i],所以还是匹配t[i]
			}
		}
	}
	if(flag == 1)
		printf("-1\n");
	else{
		printf("%lld\n",ans);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值