Segmentation fault is on terminal. Its the code to convert string to binary tree - data-structures

Node * create(Node * root, int I, int J, string str)
{
if (I == J) { root -> data =str[I]; root -> left=NULL; root -> right=NULL; }
int i = 0, j = 0, k = 0, l = 0;
//// to store the data of root
string val;
for (i = I; i < J; i++) {
if (str[i] == '(') break;
val.push_back(str[i]);
}
root -> data = stoi(val);
stack < char > st;
for (j = i; j < J; j++) {
if (str[j] == '(') st.push(str[j]);
else if (str[j] == ')') st.pop();
if (st.empty()) break;
}
for (l = j + 1; l < J; l++) {
if (str[l] == '(') st.push(str[l]);
else if (str[l] == ')') st.pop();
if (st.empty()) break;
}
k = j + 1;
if (j - i == 2) root -> left -> data = str[i + 1];
else
root -> left = create(root -> left, i + 1, j - 1, str);
if (l == k) root -> right=NULL;
else if (l - k == 2) root -> right -> data = str[k + 1];
else
root -> right = create(root -> right, k + 1, l - 1, str);
return root;
}
Node * treeFromString(string str){
Node * p = create(p, 0, str.size() - 1, str);
return p;
}
Here I have initialized variables i , j , k , l to track the left child and right child bracket in the string. I , J are the range of the node for a particular activation record of recursion.

I assume you parsed some expression, by your code I pre-implemented it.
I just implement build a tree for following expression:
expression: |<symbol>| <integer> '(' <expression> ')' '('<expression>')'
symbol : any C++ `char` single byte character.
integer : any C++ valid int type value.
#include <iostream>
#include <string>
#include <string_view> // C++17 std::string_view
#include <charconv> // C++17 std::from_chars.
#include <cassert>
//simulate Node class
struct Node
{
Node *left, *right;
int data;
};
//1. use string_view instead of triple I, J, std::string.
//2. First argument Node* root - needn't. It should be local variable.
Node * create(std::string_view str)
{
assert(!str.empty());
if (str.size() == 1)
{
Node* root = new Node; //-> YOU should allocate a memory for root.
root -> data =str[0];
root -> left=nullptr; // use nullptr instead of NULL for c++11 or later.
root -> right=nullptr;
return root; // exit needed!
}
Node* root = new Node;
root->left = nullptr;
root->right = nullptr;
root->data = 0;
//// to store the data of root
//2. THERE NEED take an integer until first '(' symbol.
{
std::size_t i = 0;
while (i < str.size() && str[i] != '(' )
++i;
// str[0 .. i) - interval is an integer.
int val = 0;
(void)std::from_chars(str.data(), str.data() + i, val); // FOR simplifity don't check validness of conversation.
str.remove_prefix(i);
root->data = val;
}
//3. SKIP balanced '(' and ')'
/*stack < char > st;
for (j = i; j < J; j++) {
if (str[j] == '(') st.push(str[j]);
else if (str[j] == ')') st.pop();
if (st.empty()) break;
}
* */
/** we can implement it another way */
assert(!str.empty() && str[0] == '(' );
std::string_view within_bracket;
{
int balanced_brackets = 0;
std::size_t i = 0;
while (i < str.size())
{
if (str[i] == '(') ++ balanced_brackets;
else if (str[i] == ')' ) --balanced_brackets;
i++;
if (balanced_brackets == 0)
break;
}
assert (i > 0 && str[ i - 1 ] == ')' );
// 0 1 2 3
// str[0..i) - is '(' ... ')' symbols.
within_bracket = std::string_view(str.data() + 1, i - 2);
str.remove_prefix(i);
}
/****4. THIS second balanced bracket check */
std::string_view second_within_bracket;
/*
for (l = j + 1; l < J; l++) {
if (str[l] == '(') st.push(str[l]);
else if (str[l] == ')') st.pop();
if (st.empty()) break;
}
k = j + 1;
*/
assert(!str.empty() && str[0] == '(' );
// ========== second balanced brackets check ==========
{
std::size_t i = 0;
int balanced_brackets = 0;
while (i < str.size())
{
if (str[i] == '(') ++ balanced_brackets;
else if (str[i] == ')' ) --balanced_brackets;
i++;
if (balanced_brackets == 0)
break;
}
// 0 1 2 3
// str[0..i) - is '(' ... ')' symbols.
second_within_bracket = std::string_view(str.data() + 1, i - 2);
str.remove_prefix(i);
}
//================================
/*
if (j - i == 2) root -> left -> data = str[i + 1];
else
root -> left = create(i + 1, j - 1, str);
if (l == k) root -> right=NULL;
else if (l - k == 2) root -> right -> data = str[k + 1];
else
root -> right = create(root -> right, k + 1, l - 1, str);
*/
root->left = create(within_bracket);
root->right = create(second_within_bracket);
return root;
}
Node * treeFromString(std::string_view str){
Node * p = create(str);
return p;
}
void printTree(Node* root, int level = 0)
{
if (root==nullptr) return;
for (int i= 0; i < level; ++i) std::cout << "--";
std::cout << " data = " << root->data << std::endl;
printTree(root->left, level + 1);
printTree(root->right, level + 1);
}
int main(){
std::string str = "12(8(7)(5))(9(3)(2(1)(8)))";
Node * expr = treeFromString(str);
printTree(expr);
}
godbold output:
Program returned: 0
data = 12
-- data = 8
---- data = 55
---- data = 53
-- data = 9
---- data = 51
---- data = 2
------ data = 49
------ data = 56

This answer is a bit different, it assumes you are loading a tree of integer values from a string, that could be loaded from a file. Next time you ask a question about code, could you please explain a little bit what the code does? Guessing does take some time and some effort.
I've reused the main() and PrintTree() functions from Khurshid Normuradov's answer. I hope he won't mind.
I took the liberty to add modern c++ coding techniques because this question is tagged c++17, so you're getting an example in c++17.
#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
struct Node {
std::unique_ptr<Node> left = nullptr;
std::unique_ptr<Node> right = nullptr;
int value = 0;
};
std::unique_ptr<Node> treeFromString(std::string_view str) {
std::cout << "treeFromString(\"" << str << "\")\n";
if (str.empty()) return {};
auto node = std::make_unique<Node>();
// extract an int
auto pos = str.find_first_not_of("0123456789");
auto val = str.substr(0, pos);
// optional: std::stoi() would throw anyway in this case
if (val.empty())
throw std::runtime_error("invalid value in expression");
node->value = std::stoi(std::string{val});
if (val.length() == str.length()) return node;
str = str.substr(val.length());
// Both left/right parsing are similar and use this
// common subroutine.
// expects parens delimited string as input.
// param str in: str string to parse from
// out: whatever's left to parse
// returns string content within parens, parens not included.
auto extract_parens_contents = [](std::string_view& str) {
// right here would be the perfect place to insert code to skip
// whitespace if you ever needed to do that.
// find parens extent
int parens = 0;
auto parens_end =
std::find_if(str.begin(), str.end(), [&parens](char c) {
parens += (c == '(') - (c == ')');
return (parens == 0);
});
if (parens_end == str.end())
throw std::runtime_error("unbalanced parens in expression");
// extract result
auto result = std::string_view(
str.begin() + 1, std::distance(str.begin() + 1, parens_end));
// remove spent bytes from input stream
str = std::string_view(
parens_end + 1,
str.length() - std::distance(str.begin(), parens_end + 1));
return result;
};
node->left = treeFromString(extract_parens_contents(str));
node->right = treeFromString(extract_parens_contents(str));
return node;
}
// special thanks to user Khurshid Normuradov, who originally wrote the two functions below.
// it would be difficult to writing something that would be any better for the
// intended purpose.
void printTree(Node* root, int level = 0) {
if (root == nullptr) return;
for (int i = 0; i < level; ++i) std::cout << "--";
std::cout << " data = " << root->value << std::endl;
printTree(root->left.get(), level + 1);
printTree(root->right.get(), level + 1);
}
int main() {
std::string str = "12(8(7)(5))(9(3)(2(1)(8)))";
auto expr = treeFromString(str);
printTree(expr.get());
}
You can play with the code here: https://godbolt.org/z/ch3zv5KTT

Related

Finding longest sequence of '1's in a binary array by replacing any one '0' with '1'

I have an array which is constituted of only 0s and 1s. Task is to find index of a 0, replacing which with a 1 results in the longest possible sequence of ones for the given array.
Solution has to work within O(n) time and O(1) space.
Eg:
Array - 011101101001
Answer - 4 ( that produces 011111101001)
My Approach gives me a result better than O(n2) but times out on long string inputs.
int findIndex(int[] a){
int maxlength = 0; int maxIndex= -1;
int n=a.length;
int i=0;
while(true){
if( a[i] == 0 ){
int leftLenght=0;
int j=i-1;
//finding count of 1s to left of this zero
while(j>=0){
if(a[j]!=1){
break;
}
leftLenght++;
j--;
}
int rightLenght=0;
j=i+1;
// finding count of 1s to right of this zero
while(j<n){
if(a[j]!=1){
break;
}
rightLenght++;
j++;
}
if(maxlength < leftLenght+rightLenght + 1){
maxlength = leftLenght+rightLenght + 1;
maxIndex = i;
}
}
if(i == n-1){
break;
}
i++;
}
return maxIndex;
}
The approach is simple, you just need to maintain two numbers while iterating through the array, the current count of the continuous block of one, and the last continuous block of one, which separated by zero.
Note: this solution assumes that there will be at least one zero in the array, otherwise, it will return -1
int cal(int[]data){
int last = 0;
int cur = 0;
int max = 0;
int start = -1;
int index = -1;
for(int i = 0; i < data.length; i++){
if(data[i] == 0){
if(max < 1 + last + cur){
max = 1 + last + cur;
if(start != -1){
index = start;
}else{
index = i;
}
}
last = cur;
start = i;
cur = 0;
}else{
cur++;
}
}
if(cur != 0 && start != -1){
if(max < 1 + last + cur){
return start;
}
}
return index;
}
O(n) time, O(1) space
Live demo: https://ideone.com/1hjS25
I believe the problem can we solved by just maintaining a variable which stores the last trails of 1's that we saw before reaching a '0'.
int last_trail = 0;
int cur_trail = 0;
int last_seen = -1;
int ans = 0, maxVal = 0;
for(int i = 0; i < a.size(); i++) {
if(a[i] == '0') {
if(cur_trail + last_trail + 1 > maxVal) {
maxVal = cur_trail + last_trail + 1;
ans = last_seen;
}
last_trail = cur_trail;
cur_trail = 0;
last_seen = i;
} else {
cur_trail++;
}
}
if(cur_trail + last_trail + 1 > maxVal && last_seen > -1) {
maxVal = cur_trail + last_trail + 1;
ans = last_seen;
}
This can be solved by a technique that is known as two pointers. Most two-pointers use O(1) space and O(n) time.
Code : https://www.ideone.com/N8bznU
#include <iostream>
#include <string>
using namespace std;
int findOptimal(string &s) {
s += '0'; // add a sentinel 0
int best_zero = -1;
int prev_zero = -1;
int zeros_in_interval = 0;
int start = 0;
int best_answer = -1;
for(int i = 0; i < (int)s.length(); ++i) {
if(s[i] == '1') continue;
else if(s[i] == '0' and zeros_in_interval == 0) {
zeros_in_interval++;
prev_zero = i;
}
else if(s[i] == '0' and zeros_in_interval == 1) {
int curr_answer = i - start; // [start, i) only contains one 0
cout << "tried this : [" << s.substr(start, i - start) << "]\n";
if(curr_answer > best_answer) {
best_answer = curr_answer;
best_zero = prev_zero;
}
start = prev_zero + 1;
prev_zero = i;
}
}
cout << "Answer = " << best_zero << endl;
return best_zero;
}
int main() {
string input = "011101101001";
findOptimal(input);
return 0;
}
This is an implementation in C++. The output looks like this:
tried this : [0111]
tried this : [111011]
tried this : [1101]
tried this : [10]
tried this : [01]
Answer = 4

For a given string which contains only digits , what's the optimal approach to return all valid ip address combinations?

Example:
Given “25525511135”
Output : [“255.255.11.135”, “255.255.111.35”]. (sorted order)
Kindly let me know if we could do a depth first search over here ?(that's the only thing striking me )
Why is it important to have an 'optimal' approach for answering this?
There are not many permutations so the simple approach of checking every combination that fits into the IP format and then filtering out those that have out of range numbers will easily work.
It's unlikely to be a bottle neck for whatever this is part of.
You probably want a dynamic programming algorithm for the general case (something like
http://www.geeksforgeeks.org/dynamic-programming-set-32-word-break-problem/).
Instead of testing whether prefixes can be segmented into words in the dictionary, you'd be testing to see whether the prefixes are prefixes of some valid IPv4 address.
Brutal DFS is acceptable in this problem:
class Solution{
private:
vector<string> ans;
int len;
string cur, rec, str;
bool IsOk(string s) {
if(s[0] == '0' && s.size() > 1) return false;
int sum = 0;
for(int i = 0; i < s.size(); i ++) {
if(s[i] == '.') return false;
sum = sum * 10 + s[i] - '0';
}
if(sum >= 0 && sum <= 255) return true;
return false;
}
void dfs(int x, int cnt) {
if(x == len) {
if(str.size() != len + 4) return ;
string tmp(str);
tmp.erase(tmp.size() - 1, 1);
if(cnt == 4) ans.push_back(tmp);
return ;
}
if(cnt > 4 || str.size() > len + 4) return ;
string tmp = cur;
cur += rec[x];
if(!IsOk(cur)) {
cur = tmp;
return ;
}
dfs(x + 1, cnt);
string tmp2 = cur + '.';
str += tmp2;
cur = "";
dfs(x + 1, cnt + 1);
str.erase(str.size() - tmp2.size(), tmp2.size());
cur = tmp;
}
public:
vector<string> restoreIpAddresses(string s) {
this->len = s.size();
this->rec = s;
cur = str = "";
ans.clear();
dfs(0, 0);
return ans;
}
};
Here is a recursive solution on JavaScript. The result is not sorted.
// Task from https://www.geeksforgeeks.org/program-generate-possible-valid-ip-addresses-given-string/
// Given a string containing only digits, restore it by returning all possible valid IP address combinations.
//
// Example:
// Input : 25525511135
// Output : [“255.255.11.135”, “255.255.111.35”]
//
(function () {
function getValidIP(str) {
const result = [];
const length = str.length;
check(0, 0, '');
function check(start, level, previous){
let i = 0;
let num;
if (level === 3) {
num = str.substring(start);
if (num && num < 256) {
result.push(`${previous}.${num}`);
}
return;
}
num = str.substring(start, start + 1);
if (num == 0) {
check(start + 1, level + 1, level === 0 ? `${num}`: `${previous}.${num}`);
} else {
while (num.length < 4 && num < 256 && start + i + 1 < length) {
check(start + i + 1, level + 1, level === 0 ? `${num}`: `${previous}.${num}`);
i++;
num = str.substring(start, start + i + 1);
}
}
}
return result;
}
console.log('12345:')
console.time('1-1');
console.log(getValidIP('12345'));
console.timeEnd('1-1');
console.log('1234:')
console.time('1-2');
console.log(getValidIP('1234'));
console.timeEnd('1-2');
console.log('2555011135:')
console.time('1-3');
console.log(getValidIP('2555011135'));
console.timeEnd('1-3');
console.log('222011135:')
console.time('1-4');
console.log(getValidIP('222011135'));
console.timeEnd('1-4');
})();

How to find edges in route

Let's say I have a graph like this
I want to find all the edges from 1 to 3 i.e. 1 2... 2 4... 4 3. I can write the code for 1 to 5 quite easily but when the next node in descending order then my code doesn't work. Please help me with that.
Here is my code:-
given if there is edge between i and j then:-
arr[i][j]=0
where s is total number of nodes and i have to find edges between a and b
for(int i=a;i!=b;)
{
for(int j=1;j<=s;j++)
{
if(arr[i][j]==0)
{
//cout<<i<<" "<<j<<endl;
i=j;
}
}
}
This can be solved using Breadth first search algorithm we can keep track of the parent of the current node while performing a BFS, and then can construct the path from that if the path exists, i have written a c++ solution below
#include<iostream>
#include<queue>
using namespace std;
int n, arr[100][100], par[100], vis[100], ans[100];
void bfs(int start, int end){
queue<int> Q;
Q.push(start);
par[start] = -1;vis[start] = 1;
bool found = false;
while(Q.size() > 0){
int v = Q.front();
Q.pop();
if(v == end){
found = true;
break;
}
for(int i = 1;i <= n;i++){
if(arr[v][i] == 0 || vis[i] == 1) continue;
Q.push(i);vis[i] = 1;
par[i] = v;
}
}
if(found == false){
cout << "No Path Found" << endl;return;
}
int curr = end, len = 0;
while(curr != -1){
ans[len++] = curr;
curr = par[curr];
}
for(int i = len-1;i >= 1;i--) cout << ans[i] << " " << ans[i-1] << endl;
}
int main(){
n = 5;
arr[1][2] = 1;arr[2][1] = 1;
arr[2][4] = 1;arr[4][2] = 1;
arr[4][5] = 1;arr[5][4] = 1;
arr[3][4] = 1;arr[4][3] = 1;
bfs(1, 3);
return 0;
}
Link to solution on Ideone : http://ideone.com/X8QnNu

Run length encoding using O(1) space

Can we do the run-length encoding in place(assuming the input array is very large)
We can do for the cases such as AAAABBBBCCCCDDDD
A4B4C4D4
But how to do it for the case such as ABCDEFG?
where the output would be A1B1C1D1E1F1G1
My first thought was to start encoding from the end, so we will use the free space (if any), after that we can shift the encoded array to the start. A problem with this approach is that it will not work for AAAAB, because there is no free space (it's not needed for A4B1) and we will try to write AAAAB1 on the first iteration.
Below is corrected solution:
(let's assume the sequence is AAABBC)
encode all groups with two or more elements and leave the rest unchanged (this will not increase length of the array) -> A3_B2C
shift everything right eliminating empty spaces after first step -> _A3B2C
encode the array from the start (reusing the already encoded groups of course) -> A3B2C1
Every step is O(n) and as far as I can see only constant additional memory is needed.
Limitations:
Digits are not supported, but that anyway would create problems with decoding as Petar Petrov mentioned.
We need some kind of "empty" character, but this can be worked around by adding zeros: A03 instead of A3_
C++ solution O(n) time O(1) space
string runLengthEncode(string str)
{
int len = str.length();
int j=0,k=0,cnt=0;
for(int i=0;i<len;i++)
{
j=i;
cnt=1;
while(i<len-1 && str[i]==str[i+1])
{
i++;
cnt++;
}
str[k++]=str[j];
string temp =to_string(cnt);
for(auto m:temp)
str[k++] = m;
}
str.resize(k);
return str;
}
null is used to indicate which items are empty and will be ignored for encoding. Also you can't encode digits (AAA2222 => A324 => 324 times 'A', but it's A3;24). Your question opens more questions.
Here's a "solution" in C#
public static void Encode(string[] input)
{
var writeIndex = 0;
var i = 0;
while (i < input.Length)
{
var symbol = input[i];
if (symbol == null)
{
break;
}
var nextIndex = i + 1;
var offset = 0;
var count = CountSymbol(input, symbol, nextIndex) + 1;
if (count == 1)
{
ShiftRight(input, nextIndex);
offset++;
}
input[writeIndex++] = symbol;
input[writeIndex++] = count.ToString();
i += count + offset;
}
Array.Clear(input, writeIndex, input.Length - writeIndex);
}
private static void ShiftRight(string[] input, int nextIndex)
{
var count = CountSymbol(input, null, nextIndex, (a, b) => a != b);
Array.Copy(input, nextIndex, input, nextIndex + 1, count);
}
private static int CountSymbol(string[] input, string symbol, int nextIndex)
{
return CountSymbol(input, symbol, nextIndex, (a, b) => a == b);
}
private static int CountSymbol(string[] input, string symbol, int nextIndex, Func<string, string, bool> cmp)
{
var count = 0;
var i = nextIndex;
while (i < input.Length && cmp(input[i], symbol))
{
count++;
i++;
}
return count;
}
The 1st solution does not take care of single characters. For example - 'Hi!' will not work. I've used totally different approach, used 'insert()' functions to add inplace. This take care of everything, whether the total 'same' character is > 10 or >100 or = 1.
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
string name = "Hello Buddy!!";
int start = 0;
char distinct = name[0];
for(int i=1;i<name.length()+1;){
if(distinct!=name[i]){
string s = to_string(i-start);
name.insert(start+1,s);
name.erase(name.begin() + start + 1 + s.length(),name.begin() + s.length() + i);
i=start+s.length()+1;
start=i;
distinct=name[start];
continue;
}
i++;
}
cout<<name;
}
Suggest me if you find anything incorrect.
O(n), in-place RLE, I couldn't think better than this. It will not place a number, if chars occurence is just 1. Will also place a9a2, if the character comes 11 times.
void RLE(char *str) {
int len = strlen(str);
int count = 1, j = 0;
for (int i = 0; i < len; i++){
if (str[i] == str[i + 1])
count++;
else {
int times = count / 9;
int rem = count % 9;
for (int k = 0; k < times; k++) {
str[j++] = str[i];
_itoa(9, &str[j++], 10);
count = count - 9;
}
if (count > 1) {
str[j++] = str[i];
_itoa(rem, &str[j++], 10);
count = 1;
}
else
str[j++] = str[i];
}
}
cout << str;
}
I/P => aaabcdeeeefghijklaaaaa
O/P => a3bcde4fghijkla5
Inplace solution using c++ ( assumes length of encoding string is not more than actual string length):
#include <bits/stdc++.h>
#include<stdlib.h>
using namespace std;
void replacePattern(char *str)
{
int len = strlen(str);
if (len == 0)
return;
int i = 1, j = 1;
int count;
// for each character
while (str[j])
{
count = 1;
while (str[j] == str[j-1])
{
j = j + 1;
count++;
}
while(count > 0) {
int rem = count%10;
str[i++] = to_string(rem)[0];
count = count/10;
}
// copy character at current position j
// to position i and increment i and j
if (str[j])
str[i++] = str[j++];
}
// add a null character to terminate string
if(str[len-1] != str[len-2]) {
str[i] = '1';
i++;
}
str[i] = '\0';
}
// Driver code
int main()
{
char str[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabccccc";
replacePattern(str);
cout << str;
return 0;
}

coupling by using dp

Given two strings, S1 & S2. given scoring scheme where gap penalty, mismatch score and match score.
Find the S1 which have a best match with S2.
My idea is to list all possible S1 and then match one by one with S2. List all possible S1 by using brute force. Then match each possible S1 with S2 by using dp.
Is there is any faster way to do so? or suggest any reference?
Using Wikipedia and a little bit of thinking one could code up something like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#define MATCH_SCORE 2
#define MISMATCH_SCORE -1
#define GAP_SCORE 0
// Calculates the match score recursively.
long MatchScore(const char* p/* in: may contain 'x' */,
const char* s/* in: doesn't contain 'x' */)
{
long res;
if (*p && *s)
{
if ((*p == *s) ||
((*p == 'x') && (*s >= 'a') && (*s <= 'f')))
{
res = MatchScore(p + 1, s + 1) + MATCH_SCORE;
}
else
{
long s1 = MatchScore(p + 1, s + 1) + MISMATCH_SCORE;
long s2 = MatchScore(p, s + 1) + GAP_SCORE;
long s3 = MatchScore(p + 1, s) + GAP_SCORE;
res = MAX(s1, MAX(s2, s3));
}
}
else
{
res = GAP_SCORE * (long)(strlen(p) + strlen(s));
}
return res;
}
// Calculates the best matching string and the match score
// using dynamic programming, the score must be the same
// as returned by MatchScore().
void FindBestMatch(const char* p/* in: may contain 'x' */,
const char* s/* in: doesn't contain 'x' */,
long* score/* out: match score */,
char** match/* out: best matching string */)
{
size_t lp = strlen(p) + 1;
size_t ls = strlen(s) + 1;
size_t i, j;
long* table = (long*)malloc(lp * ls * sizeof(long));
for (i = 0; i < lp; i++)
table[0 * lp + i] = GAP_SCORE * i;
for (j = 0; j < ls; j++)
table[j * lp + 0] = GAP_SCORE * j;
for (j = 1; j < ls; j++)
{
for (i = 1; i < lp; i++)
{
if ((p[i-1] == s[j-1]) ||
((p[i-1] == 'x') && (s[j-1] >= 'a') && (s[j-1] <= 'f')))
{
table[j * lp + i] = table[(j-1) * lp + (i-1)] + MATCH_SCORE;
}
else
{
table[j * lp + i] =
MAX(table[(j-1) * lp + (i-1)] + MISMATCH_SCORE,
MAX(table[(j-1) * lp + i] + GAP_SCORE,
table[j * lp + (i-1)] + GAP_SCORE));
}
}
}
*score = table[lp * ls - 1];
// Now, trace back the score table and construct the best matching string
*match = (char*)malloc(lp);
(*match)[lp - 1] = '\0';
for (j = ls, i = lp; j || i;)
{
if ((p[i-1] == s[j-1]) ||
((p[i-1] == 'x') && (s[j-1] >= 'a') && (s[j-1] <= 'f')))
{
(*match)[i-1] = s[j-1];
j--;
i--;
}
else
{
if (table[(j-1) * lp + i] > table[j * lp + (i-1)])
{
j--;
}
else
{
(*match)[i-1] = p[i-1];
i--;
}
}
}
free(table);
}
int main(void)
{
const char* pattern = "acdxdcxecxf";
const char* str = "abdfdaaed";
long score;
char* match;
char* match2;
printf("pattern=\"%s\" str=\"%s\"\n", pattern, str);
FindBestMatch(pattern, str, &score, &match);
printf("score=%ld (recursive)\n", MatchScore(pattern, str));
printf("score=%ld best match=\"%s\"\n", score, match);
// Now repeat with the best match we've just found,
// the result must be the same
printf("\nRepeating with pattern=best match:\n\n");
printf("pattern=\"%s\" str=\"%s\"\n", match, str);
FindBestMatch(match, str, &score, &match2);
printf("score=%ld (recursive)\n", MatchScore(match, str));
printf("score=%ld best match=\"%s\"\n", score, match2);
free(match);
free(match2);
return 0;
}
Output:
pattern="acdxdcxecxf" str="abdfdaaed"
score=14 (recursive)
score=14 best match="acdfdcaecdf"
Repeating with pattern=best match:
pattern="acdfdcaecdf" str="abdfdaaed"
score=14 (recursive)
score=14 best match="acdfdcaecdf"
I wonder if there're any bugs (other than the apparent lack of error checking).

Resources