30. Substring with Concatenation of All Words

来源:互联网 发布:centos ffmpeg安装 编辑:程序博客网 时间:2024/05/21 17:44

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

For example, given:
s"barfoothefoobarman"
words["foo", "bar"]

You should return the indices: [0,9].

(order does not matter).


做法挺暴力的,就是一个个位置扫,检查从每个位置开始是否包含了words集合里面的所有串刚好一边。

整体可以用hash加速,字串匹配可以上Boyer-Moore

public class Solution {   public List<Integer> findSubstring(String s, String[] words){List<Integer> arraylist=new ArrayList<>();if(s.length()==0){for(String word : words)if(word.length()>0)return arraylist;arraylist.add(0);return arraylist;}int wordlen=words[0].length();int size=words.length;int R = 128;int[][] right=new int[size][R];for(int i=0;i<size;i++)for (int c = 0; c < R; c++)right[i][c] = -1;for(int i=0;i<size;i++)for (int j = 0; j < words[i].length(); j++)right[i][words[i].charAt(j)] = j;HashSet<Integer> hashset=new HashSet<>(20000);HashSet<Integer> matchhashset=new HashSet<>(6000);L1:for(int i=0;i+size*wordlen<=s.length();i++){String checknow=s.substring(i, i+size*wordlen);int hash=checknow.hashCode();if(!hashset.contains(hash))hashset.add(hash);else {if(matchhashset.contains(hash))arraylist.add(i);continue;}boolean[] find=new boolean[size];for(int j=1;j<=size;j++){int start=i+(j-1)*wordlen;int end=i+j*wordlen;String sub=s.substring(start, end);boolean success=false;for(int m=0;m<size;m++)if(!find[m]){if(search(sub, words[m], right[m])==true){find[m]=true;success=true;break;}}if(!success)continue L1;}arraylist.add(i);matchhashset.add(hash);}for(String word:words){if(word.length()>0)return arraylist;}arraylist.add(s.length());return arraylist;}public boolean search(String txt,String pat,int[] right){int M = pat.length();int N = txt.length();int skip;for (int i = 0; i <= N - M; i += skip){skip = 0;for (int j = M - 1; j >= 0; j--)if (pat.charAt(j) != txt.charAt(i + j)){skip = j - right[txt.charAt(i + j)];if (skip < 1)skip = 1;break;}if (skip == 0)return true;}return false;}}


0 0