LeetCode刷题-190729-查找字符串中的单词组合

本文介绍了一种在字符串s中查找由words数组中所有单词按任意顺序拼接而成的子串的算法。该算法避免了全排列组合的高时间复杂度,采用滑动窗口结合字典统计的方式,有效提高了查找效率。

Substring with Concatenation of All Words

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.
Example 1:
Input:
s = “barfoothefoobarman”,
words = [“foo”,“bar”]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are “barfoor” and “foobar” respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:
Input:
s = “wordgoodgoodgoodbestword”,
words = [“word”,“good”,“best”,“word”]
Output: []

输入为一个字符串 s 和一个字符串数组 words,words 中的字符串长度是一样长的。在字符串 s 中找到子字符串的起始位置,子字符串包含 words 中的所有字符串。

static public IList<int> FindSubstring(string s, string[] words)
{
   List<int> result = new List<int>();
   if (words.Length == 0 || words[0].Length == 0 || s.Length < words.Length * words[0].Length)
   {
       return result;
   }
   int step = words[0].Length;
   Dictionary<string, int> dic_words = new Dictionary<string, int>();
   foreach (string str in words)
   {
       if (dic_words.ContainsKey(str))
       {
           dic_words[str]++;
       }
       else
       {
           dic_words.Add(str,1);
       }
   }

   for (int i = 0; i <= s.Length- step * words.Length; i++)
   {
       if (words.Contains(s.Substring(i,step)))
       {
           string[] sub_array = new string[words.Length];
           Dictionary<string, int> dic_search = new Dictionary<string, int>();
           int match_time = 0;
           for (int j = 0; j < words.Length; j++)
           {
               string key = s.Substring(i + j * step, step);
               if (dic_words.ContainsKey(key))
               {
                   if (!dic_search.ContainsKey(key))
                   {
                       dic_search.Add(key, 1);
                   }
                   else
                   {
                       dic_search[key]++;
                   }
                   if (dic_search[key] <= dic_words[key])
                   {
                       match_time++;
                   }
                   else
                   {
                       break;
                   }
               }
               else
               {
                   break;
               }
           }
           if (match_time == words.Length)
           {
               result.Add(i);
           }
       }
   }
   return result;
}

附上几个测试用例:
“aaaaaaaa”
[“aa”,“aa”,“aa”]
0,1,2

“wordgoodgoodgoodbestword”
[“word”,“good”,“best”,“word”]
0

“wordgoodgoodgoodbestword”
[“word”,“good”,“best”,“good”]
8

虽然代码是写出来了,但在解题的过程中很多次提交都因为超过时间显示被驳回。
一个失败思路是,先把数组通过排列组合把所有能组成的字符串都生成出来,后来发现当数组过大的时候(18左右),可能的结果就是 18 的阶乘,计算的时间就很长了,不可取。

下面记录解题过程遇到的知识点。
正则表达式查找字符串中所有结果的位置
MSDN上找到的例子

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b\w+es\b";
      string sentence = "NOTES: Any notes or comments are optional.";
      
      // Call Matches method without specifying any options.
      foreach (Match match in Regex.Matches(sentence, pattern))
         Console.WriteLine("Found '{0}' at position {1}", 
                           match.Value, match.Index);
      Console.WriteLine();

      // Call Matches method for case-insensitive matching.
      foreach (Match match in Regex.Matches(sentence, pattern, RegexOptions.IgnoreCase))
         Console.WriteLine("Found '{0}' at position {1}", 
                           match.Value, match.Index);
   }
}
// The example displays the following output:
//       Found 'notes' at position 11
//       
//       Found 'NOTES' at position 0
//       Found 'notes' at position 11

c# 判断两个数组值是否相等
参考网站:
https://stackoverflow.com/questions/4423318/how-to-compare-arrays-in-c
解题时候简单的string数组排列组合(递归)

static public IList<string> StringAC(string[] words)
{
    List<string> result = new List<string>();
    if (words.Length == 1)
    {
        result.Add(words[0]);
        return result;
    }
    else
    {
        for (int i = 0; i < words.Length; i++)
        {
            List<string> temp_list = new List<string>();
            for (int j = 0; j < words.Length; j++)
            {
                if (i == j) continue;
                temp_list.Add(words[j]);
            }
            if (temp_list.Count > 0)
            {
                foreach (var str in StringAC(temp_list.ToArray()))
                {
                    result.Add(words[i] + str);
                }
            }
        }
    }
    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值