Skip to content

Commit

Permalink
字符串匹配
Browse files Browse the repository at this point in the history
  • Loading branch information
tianqing.liang committed Sep 13, 2021
1 parent 7acb29b commit c171850
Show file tree
Hide file tree
Showing 52 changed files with 30,015 additions and 1,042 deletions.
2 changes: 1 addition & 1 deletion 23-MSDSort-And-BucketSort/SortingHelper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class SortingHelper {
return true;
}

static sortTest(String sortname, List? arr) {
static sortTest(String sortname, List arr) {
var now = new DateTime.now();
num startTime = now.millisecondsSinceEpoch;

Expand Down
19 changes: 19 additions & 0 deletions 24-SubString-Match/FileOperator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'dart:io';
import 'dart:convert';

/**
* 文件操作类
*/
class FileOperator{

static Future<List> getFileString(String filename) async{
Stream<List<int>> content = File(filename).openRead();
List<String> lines = await content.transform(utf8.decoder).transform(LineSplitter()).toList();
var words = [];
for(int i = 0;i<lines.length;i++){
words.addAll(lines[i].split(" ").toList());
}
words.removeWhere((element) => element == "");
return words;
}
}
42 changes: 42 additions & 0 deletions 24-SubString-Match/LC1392-hash.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
class Solution2 {
double MOD = 1e9 + 7;

String longestPrefix(String s) {
List<int> pow26 = List.filled(s.length, 0, growable: true);
pow26[0] = 1;
for (int i = 1; i < pow26.length; i++)
pow26[i] = (pow26[i - 1] * 26 % MOD).toInt();

// prehash[i]: hash(s[0...i])
List<int> prehash = List.filled(s.length, 0, growable: true);
prehash[0] = s[0].codeUnits[0] - 'a'.codeUnits[0];
for (int i = 1; i < s.length; i++)
prehash[i] =
((prehash[i - 1] * 26 + s[i].codeUnits[0] - 'a'.codeUnits[0]) % MOD)
.toInt();

// posthash[i]: hash(s[i...s.length - 1])
List<int> posthash = List.filled(s.length, 0, growable: true);
posthash[s.length - 1] = s[s.length - 1].codeUnits[0] - 'a'.codeUnits[0];
for (int i = s.length - 2; i >= 0; i--)
posthash[i] =
((pow26[s.length - i - 1] * (s[i].codeUnits[0] - 'a'.codeUnits[0]) +
posthash[i + 1]) %
MOD)
.toInt();

// s[0...len - 1], s[s.length - len...s.length - 1]
for (int len = s.length - 1; len >= 1; len--) {
if (prehash[len - 1] == posthash[s.length - len] &&
_equal(s, 0, len - 1, s.length - len, s.length - 1))
return s.substring(0, len);
}
return "";
}

bool _equal(String s, int l1, int r1, int l2, int r2) {
for (int i = l1, j = l2; i <= r1 && j <= r2; i++, j++)
if (s[i] != s[j]) return false;
return true;
}
}
25 changes: 25 additions & 0 deletions 24-SubString-Match/LC1392.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Solution {

String longestPrefix(String s) {

// s[0...len - 1], s[s.length - len...s.length - 1]
for(int len = s.length - 1; len >= 1; len --)
if(_equal(s, 0, len - 1, s.length - len, s.length - 1))
return s.substring(0, len);
return "";
}

bool _equal(String s, int l1, int r1, int l2, int r2){

for(int i = l1, j = l2; i <= r1 && j <= r2; i ++, j ++)
if(s[i] != s[j]) return false;
return true;
}


}

void main() {

print((new Solution()).longestPrefix("level"));
}
35 changes: 35 additions & 0 deletions 24-SubString-Match/LC187-RollingHash.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'dart:collection';
class Solution2 {
List<String> findRepeatedDnaSequences(String s) {

if(s.length < 10) {
return List.empty(growable: true);
};

List<int> map = List.filled(256,0, growable: true);
map['A'.codeUnits[0]] = 1;
map['C'.codeUnits[0]] = 2;
map['G'.codeUnits[0]] = 3;
map['T'.codeUnits[0]] = 4;

HashSet<int> seen = new HashSet<int>();
HashSet<String> res = new HashSet<String>();

int hash = 0;
double ten9 = 1e9;

for(int i = 0; i < 9; i ++)
hash = hash * 10 + map[s[i].codeUnits[0]];

for(int i = 9; i < s.length; i ++){

hash = hash * 10 + map[s[i].codeUnits[0]];

if(seen.contains(hash)) res.add(s.substring(i - 9, i + 1));
else seen.add(hash);

hash -= (map[s[i - 9].codeUnits[0]] * ten9).toInt();
}
return res.toList();
}
}
16 changes: 16 additions & 0 deletions 24-SubString-Match/LC187.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'dart:collection';
class Solution {
List<String> findRepeatedDnaSequences(String s) {

HashSet<String> seen = HashSet<String>();
HashSet<String> res = HashSet<String>();
for(int i = 0; i + 10 <= s.length; i ++){
String key = s.substring(i, i + 10);
if(seen.contains(key))
res.add(key);
else
seen.add(key);
}
return res.toList();
}
}
23 changes: 23 additions & 0 deletions 24-SubString-Match/Solution.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* 1147号问题使用遍历查询
*/
class Solution {
int longestDecomposition(String text) {
return _solve(text, 0, text.length - 1);
}

int _solve(String s, int left, int right) {
if (left > right) return 0;

for (int i = left, j = right; i < j; i++, j--) {
if (_equal(s, left, i, j, right)) return 2 + _solve(s, i + 1, j - 1);
}
return 1;
}

bool _equal(String s, int l1, int r1, int l2, int r2) {
for (int i = l1, j = l2; i <= r1 && j <= r2; i++, j++)
if (s[i] != s[j]) return false;
return true;
}
}
41 changes: 41 additions & 0 deletions 24-SubString-Match/Solution2.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* 1147号问题使用hash值解决
*/
class Solution2 {
double MOD = 1e9 + 7;

List<double>? pow26;

int longestDecomposition(String text) {
pow26 = List.filled(text.length, 0, growable: true);
pow26![0] = 1;
for (int i = 1; i < pow26!.length; i++)
pow26![i] = pow26![i - 1] * 26 % MOD;

return _solve(text, 0, text.length - 1);
}

int _solve(String s, int left, int right) {
if (left > right) return 0;

int prehash = 0, posthash = 0;
for (int i = left, j = right; i < j; i++, j--) {
prehash = ((prehash * 26 + (s[i].codeUnits[0] - 'a'.codeUnits[0])) % MOD)
.toInt();
posthash = (((s[j].codeUnits[0] - 'a'.codeUnits[0]) * pow26![right - j] +
posthash) %
MOD)
.toInt();

if (prehash == posthash && _equal(s, left, i, j, right))
return 2 + _solve(s, i + 1, j - 1);
}
return 1;
}

bool _equal(String s, int l1, int r1, int l2, int r2) {
for (int i = l1, j = l2; i <= r1 && j <= r2; i++, j++)
if (s[i] != s[j]) return false;
return true;
}
}
86 changes: 86 additions & 0 deletions 24-SubString-Match/SubstringMatch.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'SubstringMatchHelper.dart';
import 'FileOperator.dart';

/**
* 字符串匹配
*/
class SubstringMatch {
//粗暴强制
static int bruteforce(String s, String t) {
if (s.length < t.length) return -1;
// s[i, i + t.length - 1]
for (int i = 0; i + t.length - 1 < s.length; i++) {
int j = 0;
for (; j < t.length; j++)
if (s[i + j] != t[j]) break;
if (j == t.length) return i;
}
return -1;
}

static int rabinKarp(String s, String t) {
if (s.length < t.length) return -1;
if (t.length == 0) return 0;

int thash = 0,
B = 256;
double MOD = 1e9 + 7;
for(int i = 0; i < t.length; i ++){
thash = ((thash * B + t[i].codeUnits[0]) % MOD).toInt();
};
int hash = 0, P = 1;
for(int i = 0; i < t.length - 1; i ++)
P = (P * B % MOD).toInt();

for(int i = 0; i < t.length - 1; i ++)
hash = ((hash * B + s[i].codeUnits[0]) % MOD).toInt();

for(int i = t.length- 1; i < s.length; i ++){
hash = ((hash * B + s[i].codeUnits[0]) % MOD).toInt();
if(hash == thash && _equal(s, i - t.length + 1, t))
return i - t.length + 1;
hash = ((hash - s[i - t.length + 1].codeUnits[0] * P % MOD + MOD) % MOD).toInt();
}
return
-
1;
}

static bool _equal(String s, int l, String t) {
for (int i = 0; i < t.length; i ++)
if (s[l].codeUnits[0] + i != t[i].codeUnits[0]) return false;
return true;
}
}

void main() async {
String s1 = "hello, this is liuyubobobo.";
String t1 = "bo";
SubstringMatchHelper.matchTest("bruteforce", s1, t1);

List s2 = await FileOperator.getFileString("text2.txt");
String t2 = "china";
StringBuffer res = new StringBuffer();
for (int i = 0; i < s2.length; i++) {
res.write(s2[i]);
}

SubstringMatchHelper.matchTest("bruteforce", res.toString(), t2);

SubstringMatchHelper.matchTest("bruteforce", res.toString(), "zyx");

/// Worst case
int n = 1000000,
m = 1000;

StringBuffer s3 = new StringBuffer();
for (int i = 0; i < n; i++)
s3.write('a');

StringBuffer t3 = new StringBuffer();
for (int i = 0; i < m - 1; i++)
t3.write('a');
t3.write('b');

SubstringMatchHelper.matchTest("bruteforce", s3.toString(), t3.toString());
}
25 changes: 25 additions & 0 deletions 24-SubString-Match/SubstringMatchHelper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'SubstringMatch.dart';
class SubstringMatchHelper {

SubstringMatchHelper(){}

static void matchTest(String name, String s, String t){

int pos = -1;

int startTime = new DateTime.now().millisecondsSinceEpoch;
if(name == "bruteforce"){
pos = SubstringMatch.bruteforce(s, t);
}
int endTime = new DateTime.now().millisecondsSinceEpoch;

double time = (endTime - startTime) / 1000.0;

print(startTime);
print(endTime);
if(s.indexOf(t) != pos)
throw new Exception(name + " failed");
print("$name : res = $pos, time = $time s");
}

}
Loading

0 comments on commit c171850

Please sign in to comment.