尺取法(hiho字符串)

1. 问题描述:

如果一个字符串恰好包含2个'h'、1个'i'和1个'o',我们就称这个字符串是hiho字符串。  

例如"oihateher"、"hugeinputhugeoutput"都是hiho字符串。

现在给定一个只包含小写字母的字符串S,小Hi想知道S的所有子串中,最短的hiho字符串是哪个。

输入

字符串S  

对于80%的数据,S的长度不超过1000  

对于100%的数据,S的长度不超过100000

输出

找到S的所有子串中,最短的hiho字符串是哪个,输出该子串的长度。如果S的子串中没有hiho字符串,输出-1。

样例输入 

happyhahaiohell

样例输出

 5

 

2. 与最短摘要不同的是,hiho规定了hiho字符串的规则,但是思路与最短摘要的思路相同,都可以使用尺取法来解决

只不过这次的扫描的是字符串,最短摘要扫描的是单词,但是本质上是一样的

这里需要注意题目有一个坑就是恰好为2个h,1个i和1和o

代码如下:

import java.util.Scanner;
public class Main{
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.next();
		int res = solve(s);
		System.out.println(res);	
	}

	private static int solve(String s) {
		char a[] = s.toCharArray();
		int j = 0;
		int len = Integer.MAX_VALUE;
		int begin = 0;
		int end = -1;
		for(int i = 0;i<s.length();i++){
			char c = a[i];
			if(!check(c))continue;
			if(j==0)j=i+1;
			//判断还有更短的hiho字符串吗,但是后来想想假如更新len之后那么表示i到j就是hiho字符串不可能包括多于的字符
			if(j-i+1>=4&&j<a.length&&containAll(a,i,j)){
				if(check(a,i,j)&&j-i+1<len){
					len = j - i + 1;
					begin = i;
					end = j;
				}
			}
			while(j<a.length){
				c = a[j];
				if(!check(c)){
					j++;
					continue;
				}
				if(containAll(a,i,j)){
					if(check(a,i,j)&&j-i+1<len){
						len = j - i + 1;
						begin = i;
						end = j;
					}
					break;
				}
				//不满足也要继续扫描
				j++;
			}
		}
			//print(a,begin,end);
		return len==Integer.MAX_VALUE?-1:len;
	}

	private static void print(char[] a, int begin, int end) {
		System.out.print(begin+" "+end);
		for(int i = begin;i<=end;i++){
			System.out.print(a[i]);
		}	
	}

	private static boolean check(char[] a, int i, int j) {
		//题目规定是恰好2个h 1个i 1个o
		int c1 = 0,c2 = 0,c3 = 0;
		for(int k = i;k<=j;k++){
			if(a[k]=='h')c1++;
			if(a[k]=='i')c2++;
			if(a[k]=='o')c3++;
		}
		return c1==2&&c2==1&&c3==1;
	}

	private static boolean containAll(char[] a, int i, int j) {
		int c1 = 0,c2 = 0,c3 = 0;
		for(int k = i;k<=j;k++){
			if(a[k]=='h')c1++;
			if(a[k]=='i')c2++;
			if(a[k]=='o')c3++;
		}
		return c1>=2&&c2>=1&&c3>=1;
	}

	private static boolean check(char c) {
		return c=='h'||c=='i'||c=='o';
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值