/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
 * Created By : Vishwas Tripathi
 * CSE, MNNIT-ALLAHABAD
 * vishfrnds@gmail.com
 _._._._._._._._._._._._._._._._._._._._._.*/

#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <set>
#include <assert.h>
using namespace std;

#define MP make_pair
#define pb push_back
#define rep(i,n) for(int i=0;i<n;i++)
#define PER(i,a,b) for(int i=b;i>=a;i--)
#define X first
#define Y second
#define all(c) c.begin(),c.end() //eg sort(all(v));

#define tr(c, itr) for(itr = (c).begin(); itr != (c).end(); itr++)
#define present(container, element) (container.find(element) != container.end()) //for set,map,etc
#define cpresent(container, element) (find(all(container),element) != container.end()) //for vectors

 typedef long long ll;
 typedef vector<int> vi;
 typedef vector< vi > vvi;
 typedef pair< int,int > ii;

#define sz(a) int((a).size())
#define clr(a) memset(a,0,sizeof(a))
#define ini(a) memset(a,-1,sizeof(a))

//i/o
#define inp(n) scanf("%d",&n)
#define inp2(n,m) inp(n), inp(m)
#define ins(s) scanf("%s",s);
#define out(n) printf("%d\n",n)
#define out2(n,m) printf("%d %d\n",n,m)
#define inc(n) scanf("%c",&n)

#define inll(n) scanf("%lld",&n)
#define inll2(n,m) scanf("%lld%lld",&n,&m)
#define outll(n) printf("%lld\n",n)
#define outll(n) printf("%lld\n",n)
#define outll2(n,m) printf("%lld %lld\n",n,m)

//cost
#define MOD 1000000007
#define MOD_INV 1000000006
#define MAX 100009
#define INF 999999999

#define chk(a) cerr << endl << #a << " : " << a << endl
#define chk2(a,b) cerr << endl << #a << " : " << a << "\t" << #b << " : " << b << endl
#define chk3(a,b,c) cerr << endl << #a << " : " << a << "\t" << #b << " : " << b << "\t" << #c << " : " << c << endl
#define chk4(a,b,c,d) cerr << endl << #a << " : " << a << "\t" << #b << " : " << b << "\t" << #c << " : " << c << "\t" << #d << " : " << d << endl

#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
	const int MAXN = 3010;
	char S[MAXN];
	int N, gap;
	int sa[MAXN], pos[MAXN], tmp[MAXN], lcp[MAXN];

	bool sufCmp(int i, int j)
	{
		if (pos[i] != pos[j])
			return pos[i] < pos[j];
		i += gap;
		j += gap;
		return (i < N && j < N) ? pos[i] < pos[j] : i > j;
	}

	void buildSA()
	{
		N = strlen(S);
		REP(i, N) sa[i] = i, pos[i] = S[i];
		for (gap = 1;; gap *= 2)
		{
			sort(sa, sa + N, sufCmp);
			REP(i, N - 1) tmp[i + 1] = tmp[i] + sufCmp(sa[i], sa[i + 1]);
			REP(i, N) pos[sa[i]] = tmp[i];
			if (tmp[N - 1] == N - 1) break;
		}
	}

	void buildLCP()
	{
		for (int i = 0, k = 0; i < N; ++i) if (pos[i] != N - 1)
		{
			for (int j = sa[pos[i] + 1]; S[i + k] == S[j + k];)
			++k;
			lcp[pos[i]] = k;
			if (k)--k;
		}
	}

int fre[226];

int main()
{
	string a, b;
	cin >> a >> b;
	int x = a.length (), y = b.length ();
	rep (i, x) {
		fre[a[i]]++;
		S[i] = a[i];
	}
	S[x] = '~';
	rep (i, x) {
		S[x + 1 + i] = a[x - i - 1];
	}
	S[x + x + 1] = '~';
	bool ok = true;
	rep (i, y) {
		S[2 * x + 2 + i] = b[i];
		if (fre[b[i]] == 0)
			ok = false;
	}

	S[2 * x + y + 2] = '\0';
	if (!ok) {
		out (-1);
	}
	else {
		//vector<pair<int, int> > ans;
		int ans = 0;
		buildSA ();
		buildLCP ();
		int cur = 0;
		do {
			int r = pos[2 * x + 2 + cur];
			int l = lcp[r];
			int i = r + 1;
			//chk (r);
			for (; i < N; i++) {
				l = min (l, lcp[i - 1]);
				if (sa[i] < N - y)
					break;
			}
			//chk4 (cur, l, i, sa[i]);
			cur += l;
			if (sa[i] < x) {
				ans++;
				//ans.pb (MP (sa[i] + 1, sa[i] + 1 + l - 1));
				//printf ("%d %d\n", sa[i] + 1, sa[i] + 1 + l - 1);
			}
			else {
				ans++;
				//ans.pb (MP (x - (sa[i] - x) + 1, x - (sa[i] + l - x - 1) + 1));
				//printf ("%d %d\n", x - (sa[i] - x) + 1, x - (sa[i] + l - x - 1) + 1);
			}

		} while (cur < y);
		out (ans);

		cur = 0;
		do {
			int r = pos[2 * x + 2 + cur];
			int l = lcp[r];
			int i = r + 1;
			//chk (r);
			for (; i < N; i++) {
				l = min (l, lcp[i - 1]);
				if (sa[i] < N - y)
					break;
			}
			//chk4 (cur, l, i, sa[i]);
			cur += l;
			if (sa[i] < x) {
				//ans.pb (MP (sa[i] + 1, sa[i] + 1 + l - 1));
				printf ("%d %d\n", sa[i] + 1, sa[i] + 1 + l - 1);
			}
			else {
				//ans.pb (MP (x - (sa[i] - x) + 1, x - (sa[i] + l - x - 1) + 1));
				printf ("%d %d\n", x - (sa[i] - x) + 1, x - (sa[i] + l - x - 1) + 1);
			}

		}while (cur < y);

		/*
		cout << ans.size () << "\n";
		rep (j, ans.size ())
			out2 (ans[j].X, ans[j].Y);
			*/
	}

    return 0;
}


/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
 * Created By : Vishwas Tripathi
 * CSE, MNNIT-ALLAHABAD
 * vishfrnds@gmail.com
 _._._._._._._._._._._._._._._._._._._._._.*/

#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <set>
#include <assert.h>
using namespace std;

#define MP make_pair
#define pb push_back
#define rep(i,n) for(int i=0;i<n;i++)
#define PER(i,a,b) for(int i=b;i>=a;i--)
#define X first
#define Y second
#define all(c) c.begin(),c.end() //eg sort(all(v));

#define tr(c, itr) for(itr = (c).begin(); itr != (c).end(); itr++)
#define present(container, element) (container.find(element) != container.end()) //for set,map,etc
#define cpresent(container, element) (find(all(container),element) != container.end()) //for vectors

 typedef long long ll;
 typedef vector<int> vi;
 typedef vector< vi > vvi;
 typedef pair< int,int > ii;

#define sz(a) int((a).size())
#define clr(a) memset(a,0,sizeof(a))
#define ini(a) memset(a,-1,sizeof(a))

//i/o
#define inp(n) scanf("%d",&n)
#define inp2(n,m) inp(n), inp(m)
#define ins(s) scanf("%s",s);
#define out(n) printf("%d\n",n)
#define out2(n,m) printf("%d %d\n",n,m)
#define inc(n) scanf("%c",&n)

#define inll(n) scanf("%lld",&n)
#define inll2(n,m) scanf("%lld%lld",&n,&m)
#define outll(n) printf("%lld\n",n)
#define outll(n) printf("%lld\n",n)
#define outll2(n,m) printf("%lld %lld\n",n,m)

//cost
#define MOD 1000000007
#define MOD_INV 1000000006
#define MAX 100009
#define INF 999999999

#define chk(a) cerr << endl << #a << " : " << a << endl
#define chk2(a,b) cerr << endl << #a << " : " << a << "\t" << #b << " : " << b << endl
#define chk3(a,b,c) cerr << endl << #a << " : " << a << "\t" << #b << " : " << b << "\t" << #c << " : " << c << endl
#define chk4(a,b,c,d) cerr << endl << #a << " : " << a << "\t" << #b << " : " << b << "\t" << #c << " : " << c << "\t" << #d << " : " << d << endl

#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
	const int MAXN = 1 << 12;
	char S[MAXN];
	int N, gap;
	int sa[MAXN], pos[MAXN], tmp[MAXN], lcp[MAXN];

	bool sufCmp(int i, int j)
	{
		if (pos[i] != pos[j])
			return pos[i] < pos[j];
		i += gap;
		j += gap;
		return (i < N && j < N) ? pos[i] < pos[j] : i > j;
	}

	void buildSA()
	{
		N = strlen(S);
		REP(i, N) sa[i] = i, pos[i] = S[i];
		for (gap = 1;; gap *= 2)
		{
			sort(sa, sa + N, sufCmp);
			REP(i, N - 1) tmp[i + 1] = tmp[i] + sufCmp(sa[i], sa[i + 1]);
			REP(i, N) pos[sa[i]] = tmp[i];
			if (tmp[N - 1] == N - 1) break;
		}
	}

	void buildLCP()
	{
		for (int i = 0, k = 0; i < N; ++i) if (pos[i] != N - 1)
		{
			for (int j = sa[pos[i] + 1]; S[i + k] == S[j + k];)
			++k;
			lcp[pos[i]] = k;
			if (k)--k;
		}
	}

int fre[326];

int main()
{
	string a, b;
	cin >> a >> b;
	int x = a.length (), y = b.length ();
	rep (i, x) {
		fre[a[i]]++;
		S[i] = a[i];
	}
	S[x] = '~';
	rep (i, x) {
		S[x + 1 + i] = a[x - i - 1];
	}
	S[x + x + 1] = '~';
	bool ok = true;
	rep (i, y) {
		S[2 * x + 2 + i] = b[i];
		if (fre[b[i]] == 0)
			ok = false;
	}

	S[2 * x + y + 2] = '\0';
	if (!ok) {
		out (-1);
	}
	else {
		vector<pair<int, int> > ans;
		buildSA ();
		buildLCP ();
		int cur = 0;
		do {
			int r = pos[2 * x + 2 + cur];
			int l = lcp[r];
			int i = r + 1;
			//chk (r);
			for (; i < N; i++) {
				l = min (l, lcp[i - 1]);
				if (sa[i] < N - y)
					break;
			}
			//chk4 (cur, l, i, sa[i]);
			cur += l;
			if (sa[i] < x) {
				ans.pb (MP (sa[i] + 1, sa[i] + 1 + l - 1));
				//printf ("%d %d\n", sa[i] + 1, sa[i] + 1 + l - 1);
			}
			else {
				ans.pb (MP (x - (sa[i] - x) + 1, x - (sa[i] + l - x - 1) + 1));
				//printf ("%d %d\n", x - (sa[i] - x) + 1, x - (sa[i] + l - x - 1) + 1);
			}

		} while (cur < y);
		cout << ans.size () << "\n";
		rep (j, ans.size ())
			out2 (ans[j].X, ans[j].Y);
	}

    return 0;
}


#include<bits/stdc++.h>

// Author : Archit Jain :) Delhi Technological University
//#pragma comment (linker, "/STACK:256000000")

#define mp(x,y) make_pair(x,y)
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define pi   3.14159265358979323846264338327950288

using namespace std;
typedef long long lld;

//snippets
template<class T>  T gcd(T a,T b){if(b==0)return a;else return gcd(b,a%b);}
template<class T>T power(T a,T b){T result=1;while(b>0){if(b&1) result = result * a;a = a*a;b>>=1;}return result;}
template<class T>T powerMod(T a,T b,T c){T result =1%c;while(b>0){if(b&1)result = (result * a)%c;a = (a*a)%c;b>>=1;}return result;}
template<class T>bool prime(T a){if(a==2)return true;else if(a%2==0)return false;for(int i=3;i*i<=a;i+=2){if(a%i==0)return false;}return true;}

#define MAX 5000
#define MOD 1000000007

string a,b;
int z[MAX];

int longestPrefix(string text,int &pos,int offset)
{
    int l =0,r = 0;
    int result = 0;
    for(int i = 1;i<text.size();i++)
    {
        if(i>r)
        {
            l = r = i;
            while(r<text.size() && text[r-l]==text[r])r++;
            z[i]  = r-l;
            r--;
        }
        else
        {
            int k = i-l;
            if(z[k]<r-i+1)
            z[i] = z[k];
            else
            {
                l= i;
                while(r<text.size() && text[r-l]==text[r])r++;
                z[i] = r-l;
                r--;
            }
        }
        if(i>=offset && result<z[i])
        {
            result = z[i];
            pos = i;
        }
    }
    return result;
}

int main()
{

    cin.sync_with_stdio(0);
    cout.sync_with_stdio(0);

    cin>>a>>b;
    string c;
    c = a;
    reverse(c.begin(),c.end());
    vector<pair<int,int> > result;
    set<char> store;

    for(int i = 0;i<a.size();i++)
    store.insert(a[i]);

    for(int i = 0;i<b.size();i++)
    {
        if(store.find(b[i])==store.end())
        {
            cout<<"-1\n";
            return 0;
        }
    }

    int shift = 0;
    while(shift<b.size())
    {
        b = b.substr(shift);

        string text1 = b + "#" + a;
        string text2 = b + "#" + c;

        int p1,p2;
        int len1 = longestPrefix(text1,p1,b.size());
        int len2 = longestPrefix(text2,p2,b.size());
        int maxLen = max(len1,len2);

        p1 = p1 - b.size()-1;
        p2 = p2 - b.size()-1;

        p2 = c.size() -p2;

        if(len1>=len2)
        result.push_back(mp(p1+1,p1+maxLen));
        else
        result.push_back(mp(p2,p2+1-maxLen));

        shift=maxLen;
    }
    cout<<result.size()<<endl;

    for(int i = 0;i<result.size();i++)
        cout<<result[i].first<<" "<<result[i].second<<endl;
    return 0;
}


#include<bits/stdc++.h>

// Author : Archit Jain :) Delhi Technological University
//#pragma comment (linker, "/STACK:256000000")

#define mp(x,y) make_pair(x,y)
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define pi   3.14159265358979323846264338327950288

using namespace std;
typedef long long lld;

//snippets
template<class T>  T gcd(T a,T b){if(b==0)return a;else return gcd(b,a%b);}
template<class T>T power(T a,T b){T result=1;while(b>0){if(b&1) result = result * a;a = a*a;b>>=1;}return result;}
template<class T>T powerMod(T a,T b,T c){T result =1%c;while(b>0){if(b&1)result = (result * a)%c;a = (a*a)%c;b>>=1;}return result;}
template<class T>bool prime(T a){if(a==2)return true;else if(a%2==0)return false;for(int i=3;i*i<=a;i+=2){if(a%i==0)return false;}return true;}

#define MAX 200005
#define MOD 1000000007

string a,b;
int z[MAX];

int longestPrefix(string text,int &pos,int offset)
{
    int l =0,r = 0;
    int result = 0;
    for(int i = 1;i<text.size();i++)
    {
        if(i>r)
        {
            l = r = i;
            while(r<text.size() && text[r-l]==text[r])r++;
            z[i]  = r-l;
            r--;
        }
        else
        {
            int k = i-l;
            if(z[k]<r-l+1)
            z[i] = z[k];
            else
            {
                l= i;
                while(r<text.size() && text[r-l]==text[r])r++;
                z[i] = r-l;
                r--;
            }
        }
        if(i>offset && result<z[i])
        {
            result = z[i];
            pos = i;
        }
        //result = max(result,z[i]);

    }
    return result;
}

int main()
{

    cin.sync_with_stdio(0);
    cout.sync_with_stdio(0);

    cin>>a>>b;

    string c;

    c = a;
    reverse(c.begin(),c.end());

    vector<pair<int,int> > result;

    set<char> store;

    for(int i = 0;i<a.size();i++)
    store.insert(a[i]);

    for(int i = 0;i<b.size();i++)
    {
        if(store.find(b[i])==store.end())
        {
            cout<<"-1\n";
            return 0;
        }
    }
   // string temp = "at#aaabrytaaa";
    //int p;
    //cout<<longestPrefix(temp,p,2)<<endl;

    //for(int i = 0;i<temp.size();i++)
    //cout<<z[i]<<" ";

    //cout<<endl;
    int shift = 0;
    while(shift<b.size())
    {
        b = b.substr(shift);
        string text1 = b + "#" + a;
        string text2 = b + "#" + c;

        int p1,p2;
        int len1 = longestPrefix(text1,p1,b.size());
        int len2 = longestPrefix(text2,p2,b.size());
        int maxLen = max(len1,len2);

        p1 = p1 - b.size()-1;
        p2 = p2 - b.size()-1;

        p2 = c.size() -p2-1;

        if(len1>=len2)
        result.push_back(mp(p1+1,p1+maxLen));
        else
        result.push_back(mp(p2+1,p2+2-maxLen));

        //cout<<maxLen<<" "<<b<<endl;
        shift=maxLen;
    }
    cout<<result.size()<<endl;

    for(int i = 0;i<result.size();i++)
    {
        cout<<result[i].first<<" "<<result[i].second<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>

// Author : Archit Jain :) Delhi Technological University
//#pragma comment (linker, "/STACK:256000000")

#define mp(x,y) make_pair(x,y)
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define pi   3.14159265358979323846264338327950288

using namespace std;
typedef long long lld;

//snippets
template<class T>  T gcd(T a,T b){if(b==0)return a;else return gcd(b,a%b);}
template<class T>T power(T a,T b){T result=1;while(b>0){if(b&1) result = result * a;a = a*a;b>>=1;}return result;}
template<class T>T powerMod(T a,T b,T c){T result =1%c;while(b>0){if(b&1)result = (result * a)%c;a = (a*a)%c;b>>=1;}return result;}
template<class T>bool prime(T a){if(a==2)return true;else if(a%2==0)return false;for(int i=3;i*i<=a;i+=2){if(a%i==0)return false;}return true;}

#define MAX 5000
#define MOD 1000000007

string a,b;
int z[MAX];

int longestPrefix(string text,int &pos,int offset)
{
    int l =0,r = 0;
    int result = 0;
    for(int i = 1;i<text.size();i++)
    {
        if(i>r)
        {
            l = r = i;
            while(r<text.size() && text[r-l]==text[r])r++;
            z[i]  = r-l;
            r--;
        }
        else
        {
            int k = i-l;
            if(z[k]<r-l+1)
            z[i] = z[k];
            else
            {
                l= i;
                while(r<text.size() && text[r-l]==text[r])r++;
                z[i] = r-l;
                r--;
            }
        }
        if(i>offset && result<z[i])
        {
            result = z[i];
            pos = i;
        }
    }
    return result;
}

int main()
{

    cin.sync_with_stdio(0);
    cout.sync_with_stdio(0);

    cin>>a>>b;

    string c;

    c = a;
    reverse(c.begin(),c.end());

    vector<pair<int,int> > result;

    set<char> store;

    for(int i = 0;i<a.size();i++)
    store.insert(a[i]);

    for(int i = 0;i<b.size();i++)
    {
        if(store.find(b[i])==store.end())
        {
            cout<<"-1\n";
            return 0;
        }
    }

    int shift = 0;
    while(shift<b.size())
    {
        b = b.substr(shift);

        string text1 = b + "#" + a;
        string text2 = b + "#" + c;

        int p1,p2;
        int len1 = longestPrefix(text1,p1,b.size());
        int len2 = longestPrefix(text2,p2,b.size());
        int maxLen = max(len1,len2);

        p1 = p1 - b.size()-1;
        p2 = p2 - b.size()-1;

        p2 = c.size() -p2;

        if(len1>=len2)
        result.push_back(mp(p1+1,p1+maxLen));
        else
        result.push_back(mp(p2,p2+1-maxLen));

        shift=maxLen;
    }
    cout<<result.size()<<endl;

    for(int i = 0;i<result.size();i++)
        cout<<result[i].first<<" "<<result[i].second<<endl;
    return 0;
}


#include<bits/stdc++.h>

// Author : Archit Jain :) Delhi Technological University
//#pragma comment (linker, "/STACK:256000000")

#define mp(x,y) make_pair(x,y)
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define pi   3.14159265358979323846264338327950288

using namespace std;
typedef long long lld;

//snippets
template<class T>  T gcd(T a,T b){if(b==0)return a;else return gcd(b,a%b);}
template<class T>T power(T a,T b){T result=1;while(b>0){if(b&1) result = result * a;a = a*a;b>>=1;}return result;}
template<class T>T powerMod(T a,T b,T c){T result =1%c;while(b>0){if(b&1)result = (result * a)%c;a = (a*a)%c;b>>=1;}return result;}
template<class T>bool prime(T a){if(a==2)return true;else if(a%2==0)return false;for(int i=3;i*i<=a;i+=2){if(a%i==0)return false;}return true;}

#define MAX 5000
#define MOD 1000000007

string a,b;
int z[MAX];

int longestPrefix(string text,int &pos,int offset)
{
    int l =0,r = 0;
    int result = 0;
    for(int i = 1;i<text.size();i++)
    {
        if(i>r)
        {
            l = r = i;
            while(r<text.size() && text[r-l]==text[r])r++;
            z[i]  = r-l;
            r--;
        }
        else
        {
            int k = i-l;
            if(z[k]<r-l+1)
            z[i] = z[k];
            else
            {
                l= i;
                while(r<text.size() && text[r-l]==text[r])r++;
                z[i] = r-l;
                r--;
            }
        }
        if(i>=offset && result<z[i])
        {
            result = z[i];
            pos = i;
        }
    }
    return result;
}

int main()
{

    cin.sync_with_stdio(0);
    cout.sync_with_stdio(0);

    cin>>a>>b;
    string c;
    c = a;
    reverse(c.begin(),c.end());
    vector<pair<int,int> > result;
    set<char> store;

    for(int i = 0;i<a.size();i++)
    store.insert(a[i]);

    for(int i = 0;i<b.size();i++)
    {
        if(store.find(b[i])==store.end())
        {
            cout<<"-1\n";
            return 0;
        }
    }

    int shift = 0;
    while(shift<b.size())
    {
        b = b.substr(shift);

        string text1 = b + "#" + a;
        string text2 = b + "#" + c;

        int p1,p2;
        int len1 = longestPrefix(text1,p1,b.size());
        int len2 = longestPrefix(text2,p2,b.size());
        int maxLen = max(len1,len2);

        p1 = p1 - b.size()-1;
        p2 = p2 - b.size()-1;

        p2 = c.size() -p2;

        if(len1>=len2)
        result.push_back(mp(p1+1,p1+maxLen));
        else
        result.push_back(mp(p2,p2+1-maxLen));

        shift=maxLen;
    }
    cout<<result.size()<<endl;

    for(int i = 0;i<result.size();i++)
        cout<<result[i].first<<" "<<result[i].second<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
bool comp(int a,int b)
{
    return (a>b);
}
int gcd(long long int a,long long int b)
{
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}
int main(void) {
    string s,t,sr,c;
    cin>>s>>t;
    int i,j;
    bool b[26]={0};
    vector <pair <int,int> > ans;
    for(i=s.size()-1;i>=0;--i)
    {
        sr+=s[i];
        b[s[i]-'a']=1;
    }
    for(i=0;i<t.size();++i)
    {
        if(!b[t[i]-'a'])
        {
            cout<<"-1";
            return 0;
        }
    }
    i=0;
    pair <int,int> temp;
    while(i<t.size())
    {
        bool f=0;
        c+=t[i];
        for(j=0;j<s.size()-c.size()+1;++j)
        {
            if(s.substr(j,c.size())==c)
            {
                temp=make_pair(j+1,j+c.size());
                f=1;
                break;
            }
        }
        if(!f)
        {
            for(j=0;j<sr.size()-c.size()+1;++j)
            {
                if(sr.substr(j,c.size())==c)
                {
                    temp=make_pair(s.size()-j,s.size()-j-c.size()+1);
                    f=1;
                    break;
                }
            }
        }
        if(!f)
        {
            ans.push_back(temp);
            c.clear();
        }
        else
            i++;
    }
    ans.push_back(temp);
    cout<<ans.size()<<"\n";
    for(i=0;i<ans.size();++i)
        cout<<ans[i].first<<" "<<ans[i].second<<"\n";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
bool comp(int a,int b)
{
    return (a>b);
}
int gcd(long long int a,long long int b)
{
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}
int main(void) {
    string s,t,sr,c;
    cin>>s>>t;
    int i,j;
    bool b[26]={0};
    vector <pair <int,int> > ans;
    for(i=s.size()-1;i>=0;--i)
    {
        sr+=s[i];
        b[s[i]-'a']=1;
    }
    for(i=0;i<t.size();++i)
    {
        if(!b[t[i]-'a'])
        {
            cout<<"-1";
            return 0;
        }
    }
    i=0;
    pair <int,int> temp;
    while(i<t.size())
    {
        bool f=0;
        c+=t[i];
        for(j=0;j<s.size();++j)
        {
            if(s.substr(j,c.size())==c)
            {
                temp=make_pair(j+1,j+c.size());
                f=1;
            }
        }
        for(j=0;j<sr.size();++j)
        {
            if(sr.substr(j,c.size())==c)
            {
                temp=make_pair(s.size()-j,s.size()-j-c.size()+1);
                f=1;
            }
        }
        if(!f)
        {
            ans.push_back(temp);
            c.clear();
        }
        else
            i++;
    }
    ans.push_back(temp);
    cout<<ans.size()<<"\n";
    for(i=0;i<ans.size();++i)
        cout<<ans[i].first<<" "<<ans[i].second<<"\n";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
bool comp(int a,int b)
{
    return (a>b);
}
int gcd(long long int a,long long int b)
{
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}
int main(void) {
    string s,t,sr,c;
    cin>>s>>t;
    int i,j;
    bool b[26]={0};
    vector <pair <int,int> > ans;
    for(i=s.size()-1;i>=0;--i)
    {
        sr+=s[i];
        b[s[i]-'a']=1;
    }
    for(i=0;i<t.size();++i)
    {
        if(!b[t[i]-'a'])
        {
            cout<<"-1";
            return 0;
        }
    }
    i=0;
    pair <int,int> temp;
    while(i<t.size())
    {
        bool f=0;
        c+=t[i];
        for(j=0;j<s.size()-c.size()+1;++j)
        {
            if(s.substr(j,c.size())==c)
            {
                temp=make_pair(j+1,j+c.size());
                f=1;
            }
        }
        if(!f)
        {
            for(j=0;j<sr.size()-c.size()+1;++j)
            {
                if(sr.substr(j,c.size())==c)
                {
                    temp=make_pair(s.size()-j,s.size()-j-c.size()+1);
                    f=1;
                }
            }
        }
        if(!f)
        {
            ans.push_back(temp);
            c.clear();
        }
        else
            i++;
    }
    ans.push_back(temp);
    cout<<ans.size()<<"\n";
    for(i=0;i<ans.size();++i)
        cout<<ans[i].first<<" "<<ans[i].second<<"\n";
    return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int MAXN=2110,base=131,mod=1000000009,inf=0x3f3f3f3f,MAXS=4500000,MAXP=999973;
char target[MAXN],str[MAXN];
int n,m,tot,f[MAXN],g[MAXN],next[MAXS],real[MAXS],head[MAXP];
pii way[MAXN][MAXN],save[MAXS];
inline void insert(int key,pii val)
{
	int p=key%MAXP;
	tot++;
	real[tot]=key,save[tot]=val,next[tot]=head[p];
	head[p]=tot;
}
inline pii query(int key)
{
	int p=key%MAXP;
	for(int i=head[p];i;i=next[i])
		if(real[i]==key)return save[i];
	return pii(0,0);
}
inline void init()
{
	scanf("%s%s",str+1,target+1);
	n=strlen(target+1),m=strlen(str+1);
	for(int i=1;i<=m;i++)
	{
		int val=0;
		for(int j=i;j<=m;j++)
		{
			val=((LL)val*base+str[j])%mod;
			insert(val,pii(i,j));
		}
	}
	for(int i=m;i>=1;i--)
	{
		int val=0;
		for(int j=i;j>=1;j--)
		{
			val=((LL)val*base+str[j])%mod;
			insert(val,pii(i,j));
		}
	}
	for(int i=1;i<=n;i++)
	{
		int val=0;
		for(int j=i;j<=n;j++)
		{
			val=((LL)val*base+target[j])%mod;
			way[i][j]=query(val);
		}
	}
}
inline void solve()
{
	for(int i=1;i<=n;i++)
	{
		f[i]=inf;
		for(int j=0;j<i;j++)
			if(way[j+1][i].first&&f[j]+1<f[i])f[i]=f[j]+1,g[i]=j;
	}
}
inline void output(int i)
{
	if(!i)return;
	output(g[i]);
	printf("%d %d\n",way[g[i]+1][i].first,way[g[i]+1][i].second);
}
int main(void)
{
	init();
	solve();
	if(f[n]==inf)printf("-1\n");
	else
	{
		printf("%d\n",f[n]);
		output(n);
	}
	return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int MAXN=2110,base1=131,base2=37,mod1=1000000009,mod2=998244353,inf=0x3f3f3f3f,MAXS=4500000,MAXP=999973;
char target[MAXN],str[MAXN];
int n,m,tot,f[MAXN],g[MAXN],next[MAXS],real1[MAXS],real2[MAXS],head[MAXP];
pii way[MAXN][MAXN],save[MAXS];
inline void insert(int key1,int key2,pii val)
{
	int p=key1%MAXP;
	tot++;
	real1[tot]=key1,real2[tot]=key2,save[tot]=val,next[tot]=head[p];
	head[p]=tot;
}
inline pii query(int key1,int key2)
{
	int p=key1%MAXP;
	for(int i=head[p];i;i=next[i])
		if(real1[i]==key1&&real2[i]==key2)return save[i];
	return pii(0,0);
}
inline void init()
{
	scanf("%s%s",str+1,target+1);
	n=strlen(target+1),m=strlen(str+1);
	for(int i=1;i<=m;i++)
	{
		int val1=0,val2=0;
		for(int j=i;j<=m;j++)
		{
			val1=((LL)val1*base1+str[j])%mod2;
			val2=val2*base2+str[j]-'a'+1;
			insert(val1,val2,pii(i,j));
		}
	}
	for(int i=m;i>=1;i--)
	{
		int val1=0,val2=0;
		for(int j=i;j>=1;j--)
		{
			val1=((LL)val1*base1+str[j])%mod2;
			val2=val2*base2+str[j]-'a'+1;
			insert(val1,val2,pii(i,j));
		}
	}
	for(int i=1;i<=n;i++)
	{
		int val1=0,val2=0;
		for(int j=i;j<=n;j++)
		{
			val1=((LL)val1*base1+target[j])%mod2;
			val2=val2*base2+target[j]-'a'+1;
			way[i][j]=query(val1,val2);
		}
	}
}
inline void solve()
{
	for(int i=1;i<=n;i++)
	{
		f[i]=inf;
		for(int j=0;j<i;j++)
			if(way[j+1][i].first&&f[j]+1<f[i])f[i]=f[j]+1,g[i]=j;
	}
}
inline void output(int i)
{
	if(!i)return;
	output(g[i]);
	printf("%d %d\n",way[g[i]+1][i].first,way[g[i]+1][i].second);
}
int main(void)
{
	init();
	solve();
	if(f[n]==inf)printf("-1\n");
	else
	{
		printf("%d\n",f[n]);
		output(n);
	}
	return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int MAXN=2110,base1=131,base2=37,mod1=1000000009,mod2=998244353,inf=0x3f3f3f3f,MAXS=4500000,MAXP=999973;
char target[MAXN],str[MAXN];
int n,m,tot,f[MAXN],g[MAXN],next[MAXS],real1[MAXS],real2[MAXS],head[MAXP];
pii way[MAXN][MAXN],save[MAXS];
inline void insert(int key1,int key2,pii val)
{
	int p=key1%MAXP;
	tot++;
	real1[tot]=key1,real2[tot]=key2,save[tot]=val,next[tot]=head[p];
	head[p]=tot;
}
inline pii query(int key1,int key2)
{
	int p=key1%MAXP;
	for(int i=head[p];i;i=next[i])
		if(real1[i]==key1&&real2[i]==key2)return save[i];
	return pii(0,0);
}
inline void init()
{
	scanf("%s%s",str+1,target+1);
	n=strlen(target+1),m=strlen(str+1);
	for(int i=1;i<=m;i++)
	{
		int val1=0,val2=0;
		for(int j=i;j<=m;j++)
		{
			val1=((LL)val1*base1+str[j])%mod1;
			val2=((LL)val2*base2+str[j]-'a'+1)%mod2;
			insert(val1,val2,pii(i,j));
		}
	}
	for(int i=m;i>=1;i--)
	{
		int val1=0,val2=0;
		for(int j=i;j>=1;j--)
		{
			val1=((LL)val1*base1+str[j])%mod1;
			val2=((LL)val2*base2+str[j]-'a'+1)%mod2;
			insert(val1,val2,pii(i,j));
		}
	}
	for(int i=1;i<=n;i++)
	{
		int val1=0,val2=0;
		for(int j=i;j<=n;j++)
		{
			val1=((LL)val1*base1+target[j])%mod1;
			val2=((LL)val2*base2+target[j]-'a'+1)%mod2;
			way[i][j]=query(val1,val2);
		}
	}
}
inline void solve()
{
	for(int i=1;i<=n;i++)
	{
		f[i]=inf;
		for(int j=0;j<i;j++)
			if(way[j+1][i].first&&f[j]+1<f[i])f[i]=f[j]+1,g[i]=j;
	}
}
inline void output(int i)
{
	if(!i)return;
	output(g[i]);
	printf("%d %d\n",way[g[i]+1][i].first,way[g[i]+1][i].second);
}
int main(void)
{
	init();
	solve();
	if(f[n]==inf)printf("-1\n");
	else
	{
		printf("%d\n",f[n]);
		output(n);
	}
	return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int MAXN=2110,base=131,mod=1000000009,inf=0x3f3f3f3f;
char target[MAXN],str[MAXN];
int n,m,f[MAXN],g[MAXN];
pii way[MAXN][MAXN];
map<int,pii> BST;
inline void init()
{
    scanf("%s%s",str+1,target+1);
    n=strlen(target+1),m=strlen(str+1);
    for(int i=1;i<=m;i++)
    {
        int val=0;
        for(int j=i;j<=m;j++)
        {
            val=((LL)val*base+str[j])%mod;
            BST[val]=pii(i,j);
        }
    }
    for(int i=m;i>=1;i--)
    {
        int val=0;
        for(int j=i;j>=1;j--)
        {
            val=((LL)val*base+str[j])%mod;
            BST[val]=pii(i,j);
        }
    }
    for(int i=1;i<=n;i++)
    {
        int val=0;
        for(int j=i;j<=n;j++)
        {
            val=((LL)val*base+target[j])%mod;
            if(BST.count(val))way[i][j]=BST[val];
        }
    }
}
inline void solve()
{
    for(int i=1;i<=n;i++)
    {
        f[i]=inf;
        for(int j=0;j<i;j++)
            if(way[j+1][i].first&&f[j]+1<f[i])f[i]=f[j]+1,g[i]=j;
    }
}
inline void output(int i)
{
    if(!i)return;
    output(g[i]);
    printf("%d %d\n",way[g[i]+1][i].first,way[g[i]+1][i].second);
}
int main(void)
{
    init();
    solve();
    if(f[n]==inf)printf("-1\n");
    else
    {
        printf("%d\n",f[n]);
        output(n);
    }
    return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <map>
#include <cassert>
#include <string>
#include <cstring>
#include <queue>

using namespace std;

#define rep(i,a,b) for(int i = a; i < b; i++)
#define S(x) scanf("%d",&x)
#define S2(x,y) scanf("%d%d",&x,&y)
#define P(x) printf("%d\n",x)
#define all(v) v.begin(),v.end()
#define FF first
#define SS second

typedef long long int LL;
typedef pair<int, int > pii;
typedef vector<int > vi;

vector<pii > ans;
string s,t;
const int N = 2500000;

int F[26][N], B[26][N];
int SF[N], SB[N];

int f,b;

void pre() {
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!F[x][idx]) {
        F[x][idx] = ++f;
        SF[f] = i + 1;
      }
      idx = F[x][idx];
    }
  }

  reverse(all(s));
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!B[x][idx]) {
        B[x][idx] = ++b;
        SB[b] = i + 1;
      }
      idx = B[x][idx];
    }
  }
}

int main() {
  cin >> s >> t;
  pre();
  int n = t.size();
  int idx = 0;
  while(idx < n) {
    int s1,l1;
    int s2,l2;
    int trieIdx;

    // fwd trie
    trieIdx = 0, l1 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!F[x][trieIdx]) break;
      l1++;
      trieIdx = F[x][trieIdx];
      s1 = SF[trieIdx];
    }

    // bkd trie
    trieIdx = 0, l2 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!B[x][trieIdx]) break;
      l2++;
      trieIdx = B[x][trieIdx];
      s2 = SB[trieIdx];
    }

    if(!l1 && !l2) {
      P(-1);
      return 0;
    }

    s2 = (int)s.size() - s2 + 1;

    if(l1 >= l2) {
      ans.push_back(make_pair(s1,s1+l1-1));
      idx += l1;
    } else {
      ans.push_back(make_pair(s2,s2-l2+1));
      idx += l2;
    }

  }
  P((int)ans.size());
  rep(i,0,ans.size()) printf("%d %d\n",ans[i].FF, ans[i].SS);
  return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <map>
#include <cassert>
#include <string>
#include <cstring>
#include <queue>

using namespace std;

#define rep(i,a,b) for(int i = a; i < b; i++)
#define S(x) scanf("%d",&x)
#define S2(x,y) scanf("%d%d",&x,&y)
#define P(x) printf("%d\n",x)
#define all(v) v.begin(),v.end()
#define FF first
#define SS second

typedef long long int LL;
typedef pair<int, int > pii;
typedef vector<int > vi;

vector<pii > ans;
string s,t;
const int N = 2400000;

int F[26][N], B[26][N];
int SF[N], SB[N];

int f,b;

void pre() {
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!F[x][idx]) {
        F[x][idx] = ++f;
        SF[f] = i + 1;
      }
      idx = F[x][idx];
    }
  }

  reverse(all(s));
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!B[x][idx]) {
        B[x][idx] = ++b;
        SB[b] = i + 1;
      }
      idx = B[x][idx];
    }
  }
}

int main() {
  cin >> s >> t;
  pre();
  int n = t.size();
  int idx = 0;
  while(idx < n) {
    int s1,l1;
    int s2,l2;
    int trieIdx;

    // fwd trie
    trieIdx = 0, l1 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!F[x][trieIdx]) break;
      l1++;
      trieIdx = F[x][trieIdx];
      s1 = SF[trieIdx];
    }

    // bkd trie
    trieIdx = 0, l2 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!B[x][trieIdx]) break;
      l2++;
      trieIdx = B[x][trieIdx];
      s2 = SB[trieIdx];
    }

    if(!l1 && !l2) {
      P(-1);
      return 0;
    }

    s2 = (int)s.size() - s2 + 1;

    if(l1 >= l2) {
      ans.push_back(make_pair(s1,s1+l1-1));
      idx += l1;
    } else {
      ans.push_back(make_pair(s2,s2-l2+1));
      idx += l2;
    }

  }
  P((int)ans.size());
  rep(i,0,ans.size()) printf("%d %d\n",ans[i].FF, ans[i].SS);
  return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <map>
#include <cassert>
#include <string>
#include <cstring>
#include <queue>

using namespace std;

#define rep(i,a,b) for(int i = a; i < b; i++)
#define S(x) scanf("%d",&x)
#define S2(x,y) scanf("%d%d",&x,&y)
#define P(x) printf("%d\n",x)
#define all(v) v.begin(),v.end()
#define FF first
#define SS second

typedef long long int LL;
typedef pair<int, int > pii;
typedef vector<int > vi;

vector<pii > ans;
string s,t;

int F[26][1000000], B[26][1000000];
int SF[1000000], SB[1000000];

int f,b;

void pre() {
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!F[x][idx]) {
        F[x][idx] = ++f;
        SF[f] = i + 1;
      }
      idx = F[x][idx];
    }
  }

  reverse(all(s));
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!B[x][idx]) {
        B[x][idx] = ++b;
        SB[b] = i + 1;
      }
      idx = B[x][idx];
    }
  }
}

int main() {
  cin >> s >> t;
  pre();
  int n = t.size();
  int idx = 0;
  while(idx < n) {
    int s1,l1;
    int s2,l2;
    int trieIdx;

    // fwd trie
    trieIdx = 0, l1 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!F[x][trieIdx]) break;
      l1++;
      trieIdx = F[x][trieIdx];
      s1 = SF[trieIdx];
    }

    // bkd trie
    trieIdx = 0, l2 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!B[x][trieIdx]) break;
      l2++;
      trieIdx = B[x][trieIdx];
      s2 = SB[trieIdx];
    }

    if(!l1 && !l2) {
      P(-1);
      return 0;
    }

    s2 = (int)s.size() - s2 + 1;

    if(l1 >= l2) {
      ans.push_back(make_pair(s1,s1+l1-1));
      idx += l1;
    } else {
      ans.push_back(make_pair(s2,s2-l2+1));
      idx += l2;
    }

  }
  P((int)ans.size());
  rep(i,0,ans.size()) printf("%d %d\n",ans[i].FF, ans[i].SS);
  return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <map>
#include <cassert>
#include <string>
#include <cstring>
#include <queue>

using namespace std;

#define rep(i,a,b) for(int i = a; i < b; i++)
#define S(x) scanf("%d",&x)
#define S2(x,y) scanf("%d%d",&x,&y)
#define P(x) printf("%d\n",x)
#define all(v) v.begin(),v.end()
#define FF first
#define SS second

typedef long long int LL;
typedef pair<int, int > pii;
typedef vector<int > vi;

vector<pii > ans;
string s,t;
const int N = 2000000;

int F[26][N], B[26][N];
int SF[N], SB[N];

int f,b;

void pre() {
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!F[x][idx]) {
        F[x][idx] = ++f;
        SF[f] = i + 1;
      }
      idx = F[x][idx];
    }
  }

  reverse(all(s));
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!B[x][idx]) {
        B[x][idx] = ++b;
        SB[b] = i + 1;
      }
      idx = B[x][idx];
    }
  }
}

int main() {
  cin >> s >> t;
  pre();
  int n = t.size();
  int idx = 0;
  while(idx < n) {
    int s1,l1;
    int s2,l2;
    int trieIdx;

    // fwd trie
    trieIdx = 0, l1 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!F[x][trieIdx]) break;
      l1++;
      trieIdx = F[x][trieIdx];
      s1 = SF[trieIdx];
    }

    // bkd trie
    trieIdx = 0, l2 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!B[x][trieIdx]) break;
      l2++;
      trieIdx = B[x][trieIdx];
      s2 = SB[trieIdx];
    }

    if(!l1 && !l2) {
      P(-1);
      return 0;
    }

    s2 = (int)s.size() - s2 + 1;

    if(l1 >= l2) {
      ans.push_back(make_pair(s1,s1+l1-1));
      idx += l1;
    } else {
      ans.push_back(make_pair(s2,s2-l2+1));
      idx += l2;
    }

  }
  P((int)ans.size());
  rep(i,0,ans.size()) printf("%d %d\n",ans[i].FF, ans[i].SS);
  return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <map>
#include <cassert>
#include <string>
#include <cstring>
#include <queue>

using namespace std;

#define rep(i,a,b) for(int i = a; i < b; i++)
#define S(x) scanf("%d",&x)
#define S2(x,y) scanf("%d%d",&x,&y)
#define P(x) printf("%d\n",x)
#define all(v) v.begin(),v.end()
#define FF first
#define SS second

typedef long long int LL;
typedef pair<int, int > pii;
typedef vector<int > vi;

vector<pii > ans;
string s,t;

int F[26][9000000], B[26][9000000];
int SF[9000000], SB[9000000];

int f,b;

void pre() {
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!F[x][idx]) {
        F[x][idx] = ++f;
        SF[f] = i + 1;
      }
      idx = F[x][idx];
    }
  }

  reverse(all(s));
  rep(i,0,s.size()) {
    int idx = 0;
    rep(j,i,s.size()) {
      int x = s[j] - 'a';
      if(!B[x][idx]) {
        B[x][idx] = ++b;
        SB[b] = i + 1;
      }
      idx = B[x][idx];
    }
  }
}

int main() {
  cin >> s >> t;
  pre();
  int n = t.size();
  int idx = 0;
  while(idx < n) {
    int s1,l1;
    int s2,l2;
    int trieIdx;

    // fwd trie
    trieIdx = 0, l1 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!F[x][trieIdx]) break;
      l1++;
      trieIdx = F[x][trieIdx];
      s1 = SF[trieIdx];
    }

    // bkd trie
    trieIdx = 0, l2 = 0;
    for(int i = idx; i < n; i++) {
      int x = t[i] - 'a';
      if(!B[x][trieIdx]) break;
      l2++;
      trieIdx = B[x][trieIdx];
      s2 = SB[trieIdx];
    }

    if(!l1 && !l2) {
      P(-1);
      return 0;
    }

    s2 = (int)s.size() - s2 + 1;

    if(l1 >= l2) {
      ans.push_back(make_pair(s1,s1+l1-1));
      idx += l1;
    } else {
      ans.push_back(make_pair(s2,s2-l2+1));
      idx += l2;
    }

  }
  P((int)ans.size());
  rep(i,0,ans.size()) printf("%d %d\n",ans[i].FF, ans[i].SS);
  return 0;
}


#include <stdio.h>
#include <string.h>

struct elem {
	int p, st;
	elem *next[27];
};

const int MaxS = 2200;
char s[MaxS], t[MaxS];
elem *head;
int n, m, res=0;
int a[MaxS], b[MaxS];

void addlr(int start) {
	elem *cur = head;
	int i, j;
	for (i = start; i < m; i++) {
		if (cur->next[s[i]-'a'] == NULL) {
			cur->next[s[i]-'a'] = new elem;
			for (j = 0; j < 27; j++) {
				if (cur->next[s[i]-'a']->next[j] != NULL) {
					cur->next[s[i]-'a']->next[j] = NULL;
				}
			}
		}
		cur = cur->next[s[i]-'a'];
		cur -> p = i;
		cur -> st = start;
	}
}

void addrl(int start) {
	elem *cur = head;
	int i, j;
	for (i = start; i >= 0; i--) {
		if (cur->next[s[i]-'a'] == NULL) {
			cur->next[s[i]-'a'] = new elem;
			for (j = 0; j < 27; j++) {
				cur->next[s[i]-'a']->next[j] = NULL;
			}
		}
		cur = cur->next[s[i]-'a'];
		cur -> p = i;
		cur -> st = start;
	}
}

void out(elem *cur) {
	for (int i = 0; i < 26; i++) {
		if (cur->next[i] != NULL) {
			printf ("%c ", i+'a');
		}
	}
	printf ("\n\n");

	for (int i = 0; i < 26; i++) {
		if (cur->next[i] != NULL) {
			printf ("%c:\n", i+'a');
			out(cur->next[i]);
		}
	}
}

int findc(int p) {
	elem *cur = head;
	int i=0;
	if ((cur->next[t[p+i] - 'a'] != NULL) == NULL) {
		return -1;
	}
	while (p+i < n && cur->next[t[p+i] - 'a'] != NULL) {
		cur = cur->next[t[p+i] - 'a'];
		i++;
	}

	a[res] = cur->st;
	b[res] = cur->p;
	res++;

	return p+i;
}

int main() {
	int i;
//	freopen ("input.txt", "r", stdin);
//	freopen ("output.txt", "w", stdout);
	scanf ("%s%s", s, t);
	m = strlen(s);
	n = strlen(t);
	head = new elem;
	for (i = 0; i < 27; i++) {
		head->next[i] = NULL;
	}
	for (i = 0; i < m; i++) {
//		printf ("i=%d (%c): ", i, s[i]);
		addlr(i);
		addrl(i);
//		printf ("\n");
	}

//	printf ("%s %s\n", s, t);
//	out(head);
	i=0;
	while (i < n && i != -1) {
//		printf ("%d\n", i);
		i = findc(i);
	}

	if (i < n && i == -1) {
		printf ("-1");
		return 0;
	}

	printf ("%d\n", res);
	for (i = 0; i < res; i++) {
		printf ("%d %d\n", a[i]+1, b[i]+1);
	}
// */
	return 0;
}


#include <stdio.h>
#include <string.h>

struct elem {
	int p, st;
	elem *next[27];
};

const int MaxS = 2200;
char s[MaxS], t[MaxS];
elem *head;
int n, m, res=0;
int a[MaxS], b[MaxS];

void addlr(int start) {
	elem *cur = head;
	int i, j;
	for (i = start; i < m; i++) {
		if (cur->next[s[i]-'a'] == NULL) {
			cur->next[s[i]-'a'] = new elem;
/*			for (j = 0; j < 27; j++) {
				cur->next[s[i]-'a']->next[j] = NULL;
			}
*/
		}
		cur = cur->next[s[i]-'a'];
		cur -> p = i;
		cur -> st = start;
	}
}

void addrl(int start) {
	elem *cur = head;
	int i, j;
	for (i = start; i >= 0; i--) {
		if (cur->next[s[i]-'a'] == NULL) {
			cur->next[s[i]-'a'] = new elem;
			for (j = 0; j < 27; j++) {
				cur->next[s[i]-'a']->next[j] = NULL;
			}
		}
		cur = cur->next[s[i]-'a'];
		cur -> p = i;
		cur -> st = start;
	}
}

void out(elem *cur) {
	for (int i = 0; i < 26; i++) {
		if (cur->next[i] != NULL) {
			printf ("%c ", i+'a');
		}
	}
	printf ("\n\n");

	for (int i = 0; i < 26; i++) {
		if (cur->next[i] != NULL) {
			printf ("%c:\n", i+'a');
			out(cur->next[i]);
		}
	}
}

int findc(int p) {
	elem *cur = head;
	int i=0;
	if ((cur->next[t[p+i] - 'a'] != NULL) == NULL) {
		return -1;
	}
	while (p+i < n && cur->next[t[p+i] - 'a'] != NULL) {
		cur = cur->next[t[p+i] - 'a'];
		i++;
	}

	a[res] = cur->st;
	b[res] = cur->p;
	res++;

	return p+i;
}

int main() {
	int i;
//	freopen ("input.txt", "r", stdin);
//	freopen ("output.txt", "w", stdout);
	scanf ("%s%s", s, t);
	m = strlen(s);
	n = strlen(t);
	head = new elem;
	for (i = 0; i < 27; i++) {
		head->next[i] = NULL;
	}
	for (i = 0; i < m; i++) {
//		printf ("i=%d (%c): ", i, s[i]);
		addlr(i);
		addrl(i);
//		printf ("\n");
	}

//	printf ("%s %s\n", s, t);
//	out(head);
	i=0;
	while (i < n && i != -1) {
//		printf ("%d\n", i);
		i = findc(i);
	}

	if (i < n && i == -1) {
		printf ("-1");
		return 0;
	}

	printf ("%d\n", res);
	for (i = 0; i < res; i++) {
		printf ("%d %d\n", a[i]+1, b[i]+1);
	}
// */
	return 0;
}


class DSU:
	nodes = []
	duplicates = []

	def __init__(self,n):
		self.nodes = [[0,0] for i in range(n)]

	def find(self,x):
		return self.nodes[x]

	def union(self,x,y):
		xRoot,yRoot = self.find(x),self.find(y)
		if xRoot[0] == yRoot[0]:
			self.duplicates.append([x,y])
			return
		connections = xRoot[1] + yRoot[1]
		xRoot_pointer__original = xRoot[0]
		yRoot_pointer__original = yRoot[0]
		if xRoot[1] > yRoot[1]:
			for node in self.nodes:
				if node[0] == yRoot_pointer__original or node[0] == xRoot_pointer__original:
					node[0] = xRoot_pointer__original
					node[1] = connections
		else:
			for node in self.nodes:
				if node[0] == xRoot_pointer__original or node[0] == yRoot_pointer__original:
					node[0] = yRoot_pointer__original
					node[1] = connections

	def insert(self,x,y):
		if self.nodes[x][0] == 0 and self.nodes[y][0] == 0:
			self.nodes[x] = [x,2]
			self.nodes[y] = [x,2]
		elif self.nodes[x][0] != 0 and self.nodes[y][0] != 0:
			self.union(x,y)
		elif self.nodes[x][0] != 0:
			self.nodes[y] = [y,1]
			self.union(x,y)
		elif self.nodes[y][0] != 0:
			self.nodes[x] = [x,1]
			self.union(x,y)

n = int(input())
dsu = DSU(n+1)
for i in range(n-1):
	a = list(map(int,input().split()))
	x,y = a[0],a[1]
	dsu.insert(x,y)

new_roads = []
not_connected = 0

for i in range(len(dsu.duplicates)):
	root1 = dsu.nodes[1][0]
	for i in range(2,len(dsu.nodes)):
		if dsu.nodes[i][0] != root1 and dsu.nodes[i] != [0,0]:
			dsu.union(root1,i)
			new_roads.append([1,i])

for i in range(0,n):
	if dsu.nodes[i] == [0,0]:
		not_connected += 1

connected = -1

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] != [0,0]:
		connected = i
		break

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] == [0,0]:
		#dsu.union(connected,i)
		new_roads.append([connected,i])

for i in range(len(new_roads)):
	print(dsu.duplicates[i][0],dsu.duplicates[i][1],new_roads[i][0],new_roads[i][1])

'''
21
7 15
13 1
14 3
4 10
2 3
16 18
17 20
16 20
8 4
3 12
2 17
13 11
16 1
13 2
13 5
8 9
6 14
3 17
16 9
13 8
'''


class DSU:
	nodes = []
	duplicates = []

	def __init__(self,n):
		self.nodes = [[0,0] for i in range(n)]

	def find(self,x):
		return self.nodes[x]

	def union(self,x,y):
		xRoot,yRoot = self.find(x),self.find(y)
		if xRoot[0] == yRoot[0]:
			self.duplicates.append([x,y])
			return
		connections = xRoot[1] + yRoot[1]
		xRoot_pointer__original = xRoot[0]
		yRoot_pointer__original = yRoot[0]
		if xRoot[1] > yRoot[1]:
			for node in self.nodes:
				if node[0] == yRoot_pointer__original or node[0] == xRoot_pointer__original:
					node[0] = xRoot_pointer__original
					node[1] = connections
		else:
			for node in self.nodes:
				if node[0] == xRoot_pointer__original or node[0] == yRoot_pointer__original:
					node[0] = yRoot_pointer__original
					node[1] = connections

	def insert(self,x,y):
		if self.nodes[x][0] == 0 and self.nodes[y][0] == 0:
			self.nodes[x] = [x,2]
			self.nodes[y] = [x,2]
		elif self.nodes[x][0] != 0 and self.nodes[y][0] != 0:
			self.union(x,y)
		elif self.nodes[x][0] != 0:
			self.nodes[y] = [y,1]
			self.union(x,y)
		elif self.nodes[y][0] != 0:
			self.nodes[x] = [x,1]
			self.union(x,y)

n = int(input())
dsu = DSU(n+1)
for i in range(n-1):
	a = list(map(int,input().split()))
	x,y = a[0],a[1]
	dsu.insert(x,y)

new_roads = []
not_connected = 0

for i in range(len(dsu.duplicates)):
	root1 = dsu.nodes[1][0]
	for i in range(2,len(dsu.nodes)):
		if dsu.nodes[i][0] != root1 and dsu.nodes[i] != [0,0]:
			dsu.union(root1,i)
			new_roads.append([1,i])
			break

for i in range(0,n):
	if dsu.nodes[i] == [0,0]:
		not_connected += 1

connected = -1

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] != [0,0]:
		connected = i
		break

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] == [0,0]:
		#dsu.union(connected,i)
		new_roads.append([connected,i])

print(len(new_roads))

for i in range(len(new_roads)):
	print(dsu.duplicates[i][0],dsu.duplicates[i][1],new_roads[i][0],new_roads[i][1])

'''
21
7 15
13 1
14 3
4 10
2 3
16 18
17 20
16 20
8 4
3 12
2 17
13 11
16 1
13 2
13 5
8 9
6 14
3 17
16 9
13 8
'''


class DSU:
	nodes = []
	duplicates = []

	def __init__(self,n):
		self.nodes = [[0,0] for i in range(n)]

	def find(self,x):
		return self.nodes[x]

	def union(self,x,y):
		xRoot,yRoot = self.find(x),self.find(y)
		if xRoot[0] == yRoot[0]:
			self.duplicates.append([x,y])
			return
		if xRoot[1] > yRoot[1]:
			for node in self.nodes:
				if node[0] == yRoot[0]:
					node[0] = xRoot[0]
					node[1] += xRoot[1]
		else:
			for node in self.nodes:
				if node[0] == xRoot[0]:
					node[0] = yRoot[0]
					node[1] += yRoot[1]

	def insert(self,x,y):
		if self.nodes[x][0] == 0 and self.nodes[y][0] == 0:
			self.nodes[x] = [x,2]
			self.nodes[y] = [x,2]
		elif self.nodes[x][0] != 0 and self.nodes[y][0] != 0:
			self.union(x,y)
		elif self.nodes[x][0] != 0:
			self.nodes[y] = [y,1]
			self.union(x,y)
		elif self.nodes[y][0] != 0:
			self.nodes[x] = [x,1]
			self.union(x,y)

n = int(input())
dsu = DSU(n+1)
for i in range(n-1):
	a = list(map(int,input().split()))
	x,y = a[0],a[1]
	dsu.insert(x,y)

new_roads = []

for i in range(len(dsu.duplicates)):
	root1 = dsu.nodes[1][0]
	for i in range(2,len(dsu.nodes)):
		if dsu.nodes[i][0] != root1:
			dsu.union(root1,i)
			new_roads.append([1,i])
			break

print(len(new_roads))

for i in range(len(dsu.duplicates)):
	print(dsu.duplicates[i][0],dsu.duplicates[i][1],new_roads[i][0],new_roads[i][1])


class DSU:
	nodes = []
	duplicates = []

	def __init__(self,n):
		self.nodes = [[0,0] for i in range(n)]

	def find(self,x):
		return self.nodes[x]

	def union(self,x,y):
		xRoot,yRoot = self.find(x),self.find(y)
		if xRoot[0] == yRoot[0]:
			self.duplicates.append([x,y])
			return
		connections = xRoot[1] + yRoot[1]
		xRoot_pointer__original = xRoot[0]
		yRoot_pointer__original = yRoot[0]
		if xRoot[1] > yRoot[1]:
			for node in self.nodes:
				if node[0] == yRoot_pointer__original or node[0] == xRoot_pointer__original:
					node[0] = xRoot_pointer__original
					node[1] = connections
		else:
			for node in self.nodes:
				if node[0] == xRoot_pointer__original or node[0] == yRoot_pointer__original:
					node[0] = yRoot_pointer__original
					node[1] = connections

	def insert(self,x,y):
		if self.nodes[x][0] == 0 and self.nodes[y][0] == 0:
			self.nodes[x] = [x,2]
			self.nodes[y] = [x,2]
		elif self.nodes[x][0] != 0 and self.nodes[y][0] != 0:
			self.union(x,y)
		elif self.nodes[x][0] != 0:
			self.nodes[y] = [y,1]
			self.union(x,y)
		elif self.nodes[y][0] != 0:
			self.nodes[x] = [x,1]
			self.union(x,y)

n = int(input())
dsu = DSU(n+1)
for i in range(n-1):
	a = list(map(int,input().split()))
	x,y = a[0],a[1]
	dsu.insert(x,y)

new_roads = []
connected = -1

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] != [0,0]:
		connected = i
		break

for i in range(len(dsu.duplicates)):
	for i in range(1,len(dsu.nodes)):
		if dsu.nodes[i][0] != dsu.nodes[connected][0] and dsu.nodes[i] != [0,0]:
			dsu.union(connected,i)
			new_roads.append([connected,i])
			break

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] == [0,0]:
		#dsu.union(connected,i)
		new_roads.append([connected,i])

print(len(new_roads))

for i in range(len(new_roads)):
	print(dsu.duplicates[i][0],dsu.duplicates[i][1],new_roads[i][0],new_roads[i][1])

'''
21
7 15
13 1
14 3
4 10
2 3
16 18
17 20
16 20
8 4
3 12
2 17
13 11
16 1
13 2
13 5
8 9
6 14
3 17
16 9
13 8

10
5 9
8 5
7 6
7 9
3 9
2 1
7 2
3 6
7 1

'''


class DSU:
	nodes = []
	duplicates = []

	def __init__(self,n):
		self.nodes = [[0,0] for i in range(n)]

	def find(self,x):
		return self.nodes[x]

	def union(self,x,y):
		xRoot,yRoot = self.find(x),self.find(y)
		if xRoot[0] == yRoot[0]:
			self.duplicates.append([x,y])
			return
		if xRoot[1] > yRoot[1]:
			for node in self.nodes:
				if node[0] == yRoot[0]:
					node[0] = xRoot[0]
					node[1] += xRoot[1]
		else:
			for node in self.nodes:
				if node[0] == xRoot[0]:
					node[0] = yRoot[0]
					node[1] += yRoot[1]

	def insert(self,x,y):
		if self.nodes[x][0] == 0 and self.nodes[y][0] == 0:
			self.nodes[x] = [x,2]
			self.nodes[y] = [x,2]
		elif self.nodes[x][0] != 0 and self.nodes[y][0] != 0:
			self.union(x,y)
		elif self.nodes[x][0] != 0:
			self.nodes[y] = [y,1]
			self.union(x,y)
		elif self.nodes[y][0] != 0:
			self.node[x] = [x,1]
			self.union(x,y)

n = int(input())
dsu = DSU(n+1)
for i in range(n-1):
	a = list(map(int,input().split()))
	x,y = a[0],a[1]
	dsu.insert(x,y)

new_roads = []

for i in range(len(dsu.duplicates)):
	root1 = dsu.nodes[1][0]
	for i in range(2,len(dsu.nodes)):
		if dsu.nodes[i][0] != root1:
			dsu.union(root1,i)
			new_roads.append([1,i])
			break

print(len(new_roads))

for i in range(len(dsu.duplicates)):
	print(dsu.duplicates[i][0],dsu.duplicates[i][1],new_roads[i][0],new_roads[i][1])


class DSU:
	nodes = []
	duplicates = []

	def __init__(self,n):
		self.nodes = [[0,0] for i in range(n)]

	def find(self,x):
		return self.nodes[x]

	def union(self,x,y):
		xRoot,yRoot = self.find(x),self.find(y)
		if xRoot[0] == yRoot[0]:
			self.duplicates.append([x,y])
			return
		connections = xRoot[1] + yRoot[1]
		xRoot_pointer__original = xRoot[0]
		yRoot_pointer__original = yRoot[0]
		if xRoot[1] > yRoot[1]:
			for node in self.nodes:
				if node[0] == yRoot_pointer__original or node[0] == xRoot_pointer__original:
					node[0] = xRoot_pointer__original
					node[1] = connections
		else:
			for node in self.nodes:
				if node[0] == xRoot_pointer__original or node[0] == yRoot_pointer__original:
					node[0] = yRoot_pointer__original
					node[1] = connections

	def insert(self,x,y):
		if self.nodes[x][0] == 0 and self.nodes[y][0] == 0:
			self.nodes[x] = [x,2]
			self.nodes[y] = [x,2]
		elif self.nodes[x][0] != 0 and self.nodes[y][0] != 0:
			self.union(x,y)
		elif self.nodes[x][0] != 0:
			self.nodes[y] = [y,1]
			self.union(x,y)
		elif self.nodes[y][0] != 0:
			self.nodes[x] = [x,1]
			self.union(x,y)

n = int(input())
dsu = DSU(n+1)
for i in range(n-1):
	a = list(map(int,input().split()))
	x,y = a[0],a[1]
	dsu.insert(x,y)

new_roads = []
not_connected = 0

for i in range(len(dsu.duplicates)):
	root1 = dsu.nodes[1][0]
	for i in range(2,len(dsu.nodes)):
		if dsu.nodes[i][0] != root1 and dsu.nodes[i] != [0,0]:
			dsu.union(root1,i)
			new_roads.append([1,i])

for i in range(0,n):
	if dsu.nodes[i] == [0,0]:
		not_connected += 1

connected = -1

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] != [0,0]:
		connected = i
		break

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] == [0,0]:
		#dsu.union(connected,i)
		new_roads.append([connected,i])

for i in range(len(new_roads)):
	print(dsu.duplicates[i][0],dsu.duplicates[i][1],new_roads[i][0],new_roads[i][1])

if len(new_roads) == 0:
	print("0")

'''
21
7 15
13 1
14 3
4 10
2 3
16 18
17 20
16 20
8 4
3 12
2 17
13 11
16 1
13 2
13 5
8 9
6 14
3 17
16 9
13 8
'''


class DSU:
	nodes = []
	duplicates = []

	def __init__(self,n):
		self.nodes = [[0,0] for i in range(n)]

	def find(self,x):
		return self.nodes[x]

	def union(self,x,y):
		xRoot,yRoot = self.find(x),self.find(y)
		if xRoot[0] == yRoot[0]:
			self.duplicates.append([x,y])
			return
		connections = xRoot[1] + yRoot[1]
		xRoot_pointer__original = xRoot[0]
		yRoot_pointer__original = yRoot[0]
		if xRoot[1] > yRoot[1]:
			for node in self.nodes:
				if node[0] == yRoot_pointer__original or node[0] == xRoot_pointer__original:
					node[0] = xRoot_pointer__original
					node[1] = connections
		else:
			for node in self.nodes:
				if node[0] == xRoot_pointer__original or node[0] == yRoot_pointer__original:
					node[0] = yRoot_pointer__original
					node[1] = connections

	def insert(self,x,y):
		if self.nodes[x][0] == 0 and self.nodes[y][0] == 0:
			self.nodes[x] = [x,2]
			self.nodes[y] = [x,2]
		elif self.nodes[x][0] != 0 and self.nodes[y][0] != 0:
			self.union(x,y)
		elif self.nodes[x][0] != 0:
			self.nodes[y] = [y,1]
			self.union(x,y)
		elif self.nodes[y][0] != 0:
			self.nodes[x] = [x,1]
			self.union(x,y)

n = int(input())
dsu = DSU(n+1)
for i in range(n-1):
	a = list(map(int,input().split()))
	x,y = a[0],a[1]
	dsu.insert(x,y)

new_roads = []
not_connected = 0
connected = -1

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] != [0,0]:
		connected = i
		break

for i in range(0,n):
	if dsu.nodes[i] == [0,0]:
		not_connected += 1

for i in range(len(dsu.duplicates)):
	for i in range(1,len(dsu.nodes)):
		if dsu.nodes[i][0] != connected and dsu.nodes[i] != [0,0]:
			dsu.union(connected,i)
			new_roads.append([connected,i])
			break

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] == [0,0]:
		#dsu.union(connected,i)
		new_roads.append([connected,i])

print(len(new_roads))

for i in range(len(new_roads)):
	print(dsu.duplicates[i][0],dsu.duplicates[i][1],new_roads[i][0],new_roads[i][1])

'''
21
7 15
13 1
14 3
4 10
2 3
16 18
17 20
16 20
8 4
3 12
2 17
13 11
16 1
13 2
13 5
8 9
6 14
3 17
16 9
13 8
'''


class DSU:
	nodes = []
	duplicates = []

	def __init__(self,n):
		self.nodes = [[0,0] for i in range(n)]

	def find(self,x):
		return self.nodes[x]

	def union(self,x,y):
		xRoot,yRoot = self.find(x),self.find(y)
		if xRoot[0] == yRoot[0]:
			self.duplicates.append([x,y])
			return
		connections = xRoot[1] + yRoot[1]
		xRoot_pointer__original = xRoot[0]
		yRoot_pointer__original = yRoot[0]
		if xRoot[1] > yRoot[1]:
			for node in self.nodes:
				if node[0] == yRoot_pointer__original or node[0] == xRoot_pointer__original:
					node[0] = xRoot_pointer__original
					node[1] = connections
		else:
			for node in self.nodes:
				if node[0] == xRoot_pointer__original or node[0] == yRoot_pointer__original:
					node[0] = yRoot_pointer__original
					node[1] = connections

	def insert(self,x,y):
		if self.nodes[x][0] == 0 and self.nodes[y][0] == 0:
			self.nodes[x] = [x,2]
			self.nodes[y] = [x,2]
		elif self.nodes[x][0] != 0 and self.nodes[y][0] != 0:
			self.union(x,y)
		elif self.nodes[x][0] != 0:
			self.nodes[y] = [y,1]
			self.union(x,y)
		elif self.nodes[y][0] != 0:
			self.nodes[x] = [x,1]
			self.union(x,y)

n = int(input())
dsu = DSU(n+1)
for i in range(n-1):
	a = list(map(int,input().split()))
	x,y = a[0],a[1]
	dsu.insert(x,y)

new_roads = []
not_connected = 0

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] != [0,0]:
		connected = i
		break

for i in range(0,n):
	if dsu.nodes[i] == [0,0]:
		not_connected += 1

connected = -1

for i in range(len(dsu.duplicates)):
	for i in range(1,len(dsu.nodes)):
		if dsu.nodes[i][0] != connected and dsu.nodes[i] != [0,0]:
			dsu.union(connected,i)
			new_roads.append([connected,i])
			break

for i in range(1,len(dsu.nodes)):
	if dsu.nodes[i] == [0,0]:
		#dsu.union(connected,i)
		new_roads.append([connected,i])

print(len(new_roads))

for i in range(len(new_roads)):
	print(dsu.duplicates[i][0],dsu.duplicates[i][1],new_roads[i][0],new_roads[i][1])

'''
21
7 15
13 1
14 3
4 10
2 3
16 18
17 20
16 20
8 4
3 12
2 17
13 11
16 1
13 2
13 5
8 9
6 14
3 17
16 9
13 8
'''


import sys
from array import array  # noqa: F401

def input():
    return sys.stdin.buffer.readline().decode('utf-8')

n = int(input())
adj = [[] for _ in range(n)]
deg = [0] * n

for u, v in (map(int, input().split()) for _ in range(n - 1)):
    adj[u - 1].append(v - 1)
    adj[v - 1].append(u - 1)
    deg[u - 1] += 1
    deg[v - 1] += 1

groups = []
remove_edge = []
visited = [0] * n
visited2 = [0] * n

def dfs(stack: list):
    while stack:
        v = stack.pop()
        deg[v] = 0
        visited2[v] = 1
        for dest in adj[v]:
            if not deg[dest]:
                continue
            deg[dest] -= 1
            if deg[dest] == 1:
                stack.append(dest)

for i in range(n):
    if visited[i]:
        continue
    visited[i] = 1
    groups.append(i + 1)
    vs = [i]
    stack = [i]
    nstack = []

    while stack:
        v = stack.pop()
        if deg[v] == 1:
            nstack.append(v)
        for dest in adj[v]:
            if not visited[dest]:
                visited[dest] = 1
                stack.append(dest)
                vs.append(dest)

    dfs(nstack)

    vs = [v for v in vs if not visited2[v]]

    while vs:
        u, v = vs[-1], [x for x in adj[vs[-1]] if not visited2[x]][0]
        adj[u].remove(v)
        adj[v].remove(u)
        deg[u] -= 1
        deg[v] -= 1
        remove_edge.append(f'{u+1} {v+1} ')
        if deg[u] == 1:
            nstack.append(u)
        if deg[v] == 1:
            nstack.append(v)

        dfs(nstack)
        vs = [v for v in vs if not visited2[v]]

ans = []
for i, s in enumerate(remove_edge):
    ans.append(s + f'{groups[i]} {groups[i+1]}')

sys.stdout.buffer.write((str(len(ans)) + '\n' + '\n'.join(ans)).encode('utf-8'))


import sys
from array import array  # noqa: F401

def input():
    return sys.stdin.buffer.readline().decode('utf-8')

n = int(input())
adj = [[] for _ in range(n)]
deg = [0] * n

for u, v in (map(int, input().split()) for _ in range(n - 1)):
    adj[u - 1].append(v - 1)
    adj[v - 1].append(u - 1)
    deg[u - 1] += 1
    deg[v - 1] += 1

groups = []
remove_edge = []
visited = [0] * n
visited2 = [0] * n

def dfs(stack: list):
    while stack:
        v = stack.pop()
        deg[v] = 0
        visited2[v] = 1
        for dest in adj[v]:
            if not deg[dest]:
                continue
            deg[dest] -= 1
            if deg[dest] == 1:
                stack.append(dest)

for i in range(n):
    if visited[i]:
        continue
    visited[i] = 1
    groups.append(i + 1)
    vs = [i]
    stack = [i]
    nstack = []

    while stack:
        v = stack.pop()
        if deg[v] <= 1:
            nstack.append(v)
        for dest in adj[v]:
            if not visited[dest]:
                visited[dest] = 1
                stack.append(dest)
                vs.append(dest)

    dfs(nstack)

    vs = [v for v in vs if not visited2[v]]

    while vs:
        u, v = vs[-1], [x for x in adj[vs[-1]] if not visited2[x]][0]
        adj[u].remove(v)
        adj[v].remove(u)
        deg[u] -= 1
        deg[v] -= 1
        remove_edge.append(f'{u+1} {v+1} ')
        if deg[u] == 1:
            nstack.append(u)
        if deg[v] == 1:
            nstack.append(v)

        dfs(nstack)
        vs = [v for v in vs if not visited2[v]]

ans = []
for i, s in enumerate(remove_edge):
    ans.append(s + f'{groups[i]} {groups[i+1]}')

sys.stdout.buffer.write((str(len(ans)) + '\n' + '\n'.join(ans)).encode('utf-8'))


import sys
from array import array  # noqa: F401

def input():
    return sys.stdin.buffer.readline().decode('utf-8')

n = int(input())
adj = [[] for _ in range(n)]
deg = [0] * n

for u, v in (map(int, input().split()) for _ in range(n - 1)):
    adj[u - 1].append(v - 1)
    adj[v - 1].append(u - 1)
    deg[u - 1] += 1
    deg[v - 1] += 1

groups = []
remove_edge = []
visited = [0] * n
visited2 = [0] * n

def dfs(stack: list):
    while stack:
        v = stack.pop()
        deg[v] = 0
        visited2[v] = 1
        for dest in adj[v]:
            if not deg[dest]:
                continue
            deg[dest] -= 1
            if deg[dest] == 1:
                stack.append(dest)

for i in range(n):
    if visited[i]:
        continue
    visited[i] = 1
    groups.append(i + 1)
    vs = [i]
    stack = [i]
    nstack = []

    while stack:
        v = stack.pop()
        if deg[v] == 1:
            nstack.append(v)
        for dest in adj[v]:
            if not visited[dest]:
                visited[dest] = 1
                stack.append(dest)
                vs.append(dest)

    dfs(nstack)

    vs = [v for v in vs if not visited2[v]]

    while vs:
        u, v = vs[-1], adj[vs[-1]][0]
        adj[u].remove(v)
        adj[v].remove(u)
        deg[u] -= 1
        deg[v] -= 1
        remove_edge.append(f'{u+1} {v+1} ')
        if deg[u] == 1:
            nstack.append(u)
        if deg[v] == 1:
            nstack.append(v)

        dfs(nstack)
        vs = [v for v in vs if not visited2[v]]

ans = []
for i, s in enumerate(remove_edge):
    ans.append(s + f'{groups[i]} {groups[i+1]}')

sys.stdout.buffer.write((str(len(ans)) + '\n' + '\n'.join(ans)).encode('utf-8'))


class DSU:
    def __init__(self, n):
        self.parent = [*range(n)]
        self.set_size = [1] * n
        self.roots = set(self.parent)

    def root(self, a):
        while a != self.parent[a]:
            a = self.parent[a]
        return a

    def join(self, a, b):
        a = self.root(a)
        b = self.root(b)

        if self.set_size[a] < self.set_size[b]:
            a, b = b, a

        if a == b:
            return False

        self.roots.remove(b)
        self.set_size[a] += self.set_size[b]
        self.set_size[b] = 0
        self.parent[b] = a

        return True

n = int(input())
roads = []

d = DSU(n)
for _ in range(n - 1):
    i = [*map(int, input().split())]
    if d.join(i[0] - 1, i[1] - 1) is False:
        roads.append(i)

ans = []

while len(d.roots) > 1 and len(roads):
    i = iter(d.roots)
    ans.append((roads[-1][0], roads[-1][1], next(i) + 1, next(i) + 1))
    d.join(ans[-1][2] - 1, ans[-1][3] - 1)
    del roads[-1]

print(len(ans))
for i in ans:
    print(*i)


n = int(input())
# 1 2 .. n
r = dict()
for i in range(1, n+1):
    r[i] = set()
for i in range(n-1):
    (a, b) = map(int, input().split())
    r[a].add(b)
    r[b].add(a)

total = set(range(1, n+1))
v = []
while len(total) > 0:
    v.append(set())
    x = total.pop()
    v[-1].add(x)
    sosed = set()
    sosed.add(x)
    total.discard(x)
    while len(sosed) > 0:
        sosed2 = set()
        for i in sosed:
            for j in r[i]:
                if j in total:
                    sosed2.add(j)
                    v[-1].add(j)
                    total.discard(j)
        sosed = sosed2.copy()

noneed = []
for z in v:
    if len(z) == 1:
        continue
    x = z.pop()
    sosed = set()
    sosed.add(x)
    pos = set()
    pos.add(x)
    while len(sosed) > 0:
        sosed2 = set()
        for i in sosed:
            for j in r[i]:
                if j in pos:
                    if j in sosed:
                        noneed.append([i, j])
                else:
                    sosed2.add(j)
            pos.add(i)
        sosed = sosed2.copy()

print(len(noneed))

for i in range(len(v)-1):
    print(noneed[i][0],noneed[i][1],v[i].pop(), v[i+1].pop())


n = int(input())
# 1 2 .. n
r = dict()
for i in range(1, n+1):
    r[i] = set()
for i in range(n-1):
    (a, b) = map(int, input().split())
    r[a].add(b)
    r[b].add(a)

total = set(range(1, n+1))
v = []
while len(total) > 0:
    v.append(set())
    x = total.pop()
    v[-1].add(x)
    sosed = set()
    sosed.add(x)
    total.discard(x)
    while len(sosed) > 0:
        sosed2 = set()
        for i in sosed:
            for j in r[i]:
                if j in total:
                    sosed2.add(j)
                    v[-1].add(j)
                    total.discard(j)
        sosed = sosed2.copy()

noneed = []
for z in v:
    x = z.pop()
    sosed = set()
    sosed.add(x)
    pos = set()
    pos.add(x)
    while len(sosed) > 0:
        sosed2 = set()
        for i in sosed:
            for j in r[i]:
                if j in pos:
                    if j in sosed:
                        noneed.append([i, j])
                else:
                    sosed2.add(j)
            pos.add(i)
        sosed = sosed2.copy()
#print(v)
print(len(noneed))

for i in range(len(v)-1):
    print(noneed[i][0],noneed[i][1],v[i].pop(), v[i+1].pop())


def an(x):
    for i in x:
        return i
    return None

n = int(input())
# 1 2 .. n
r = dict()
for i in range(1, n+1):
    r[i] = set()
edge = set()
for i in range(n-1):
    (a, b) = map(int, input().split())
    edge.add((min(a,b),max(a,b)))
    r[a].add(b)
    r[b].add(a)

total = set(range(1, n+1))
v = []
while len(total) > 0:
    v.append(set())
    x = total.pop()
    v[-1].add(x)
    sosed = set()
    sosed.add(x)
    while len(sosed) > 0:
        sosed2 = set()
        for i in sosed:
            for j in r[i]:
                if j in total:
                    sosed2.add(j)
                    v[-1].add(j)
                    total.discard(j)
        sosed = sosed2.copy()

need = set()
for z in v:
    if len(z) == 1:
        continue
    x = an(z)
    sosed = set()
    sosed.add(x)
    pos = set()
    pos.add(x)
    while len(sosed) > 0:
        sosed2 = set()
        for i in sosed:
            for j in r[i]:
                if j not in pos:
                    need.add((min(i,j),max(i,j)))
                    sosed2.add(j)
                    pos.add(j)

        sosed = sosed2.copy()

print(len(v)-1)
edge -= need
edge = list(edge)
for i in range(len(v)-1):
    print(edge[i][0],edge[i][1],an(v[i]), an(v[i+1]))


# import sys
# sys.stdin = open('input.txt', 'r')
# sys.stdout = open('output.txt', 'w')

def getPar(x):
	while (a[x] != x):
		x = a[x]
	return x

def union(x,y):
	p1 = getPar(x)
	p2 = getPar(y)
	a[p2] = p1

n = int(input())
a = [i for i in range(n+1)]
e = []

for _ in range(n-1):
	u,v = map(int,input().split())
	p1 = getPar(u)
	p2 = getPar(v)
	if (p1 == p2):
		e.append([u,v])
	else:
		union(u,v)

s = []
for i in a[1:]:
    s.append(getPar(i))
s=list(set(s))
print(len(e))
for i in range(len(e)):
	print(e[i][0],e[i][1],s[i],s[i+1])


def MakeSet(x):
     x.parent = x
     x.rank   = 0

def Union(x, y):
     xRoot = Find(x)
     yRoot = Find(y)
     if xRoot.rank > yRoot.rank:
         yRoot.parent = xRoot
     elif xRoot.rank < yRoot.rank:
         xRoot.parent = yRoot
     elif xRoot != yRoot: # Unless x and y are already in same set, merge them
         yRoot.parent = xRoot
         xRoot.rank = xRoot.rank + 1

def Find(x):
     if x.parent == x:
        return x
     else:
        x.parent = Find(x.parent)
        return x.parent

class Node:
    def __init__ (self, label):
        self.label = label
    def __str__(self):
        return self.label

if __name__ == '__main__':
    n = int(input())
    l = [Node(i) for i in range(n)]
    calles_cerrar = list()
    calles_abrir = list()
    [MakeSet(node) for node in l] #cada elemento posee su propio conjunto
    for i in range(n-1):
        a,b = list(map(int,input().strip().split()))
        if (Find(l[a-1]) != Find(l[b-1])):
            Union(l[a-1],l[b-1])
        else:
            calles_cerrar.append((a-1,b-1))
    for i in range(1,n):
        if (Find(l[0]) != Find(l[i])):
            calles_abrir.append((0,i))
            Union(l[0],l[i])
    print(len(calles_cerrar))
    for i in range(len(calles_cerrar)):
        lista = calles_cerrar[i] + calles_abrir[i]
        print(' '.join(str(p+1) for p in (lista)))


def getPar(x):
	while (p[x] != x):
		x = p[x]
	return x

def union(x,y):
	p1 = getPar(x)
	p2 = getPar(y)
	p[p2] = p1

n = int(input())
p = [i for i in range(n+1)]
e = []

for _ in range(n-1):
	u,v = map(int,input().split())
	p1 = getPar(u)
	p2 = getPar(v)
	if (p1 == p2):
		e.append([u,v])
	else:
		union(u,v)

s = []
for i in p[1:]:
    s.append(getPar(i))   # To get representative of every component

s=list(set(s))
print(len(e))
for i in range(len(e)):
	print(e[i][0],e[i][1],s[i],s[i+1])


from sys import stdin
from collections import defaultdict
input = stdin.readline

def put():
    return map(int, input().split())

def find(i):
    if i==p[i]:
        return i
    p[i]=find(p[i])
    return p[i]

def union(i,j):
    if rank[i]>rank[j]:
        i,j = j,i
    elif rank[i]==rank[j]:
        rank[j]+=1
    p[i]=j

n = int(input())
graph = [[] for i in range(n)]
extra,p,rank = [], list(range(n)), [0]*n
for _ in range(n-1):
    x,y = put()
    i,j = map(find, (x-1, y-1))
    if i!=j:
        union(i,j)
    else:
        extra.append((x,y))

s = set(map(find, range(n)))
#print(s)
x = s.pop()
print(len(s))
for y in s:
    u,v = extra.pop()
    print(u,v,x+1,y+1)


from sys import stdin
from collections import defaultdict
input = stdin.readline

def put():
    return map(int, input().split())

def find(i):
    if i==p[i]:
        return i
    p[i]=find(p[i])
    return p[i]

def union(i,j):
    if rank[i]>rank[j]:
        i,j = j,i
    elif rank[i]==rank[j]:
        rank[j]+=1
    p[i]=j

n = int(input())
graph = [[] for i in range(n)]
extra,p,rank = [], list(range(n)), [0]*n
for _ in range(n-1):
    x,y = put()
    i,j = map(find, (x-1, y-1))
    if i!=j:
        union(i,j)
    else:
        extra.append((x,y))

s = set(map(find, range(n)))
x = s.pop()
print(len(s))
for y in s:
    u,v = extra.pop()
    print(u,v,x,y)


from sys import stdin
from collections import defaultdict
input = stdin.readline

def put():
    return map(int, input().split())

def find(i):
    if i==p[i]:
        return i
    p[i]=find(p[i])
    return p[i]

def union(i,j):
    if rank[i]>rank[j]:
        i,j = j,i
    elif rank[i]==rank[j]:
        rank[j]+=1
    p[i]=j

n = int(input())
graph = [[] for i in range(n)]
extra,p,rank = [], list(range(n)), [0]*n
for _ in range(n-1):
    x,y = put()
    i,j = map(find, (x-1, y-1))
    if i!=j:
        union(i,j)
    else:
        extra.append((x,y))

s = set(map(find, range(n)))
print(s)
x = s.pop()
print(len(s))
for y in s:
    u,v = extra.pop()
    print(u,v,x+1,y+1)


# -*- coding:utf-8 -*-

"""

created by shuangquan.huang at 1/14/20

"""

import collections
import time
import os
import sys
import bisect
import heapq
from typing import List

def solve(N, edges):

    dsu = collections.defaultdict(int)

    def find(u):
        if dsu[u] == 0:
            return u

        p = find(dsu[u])
        dsu[u] = p
        return p

    def union(u, v):
        pu, pv = find(u), find(v)
        dsu[pu] = pv

    def same(u, v):
        return find(u) == find(v)

    remove = []
    for u, v in edges:
        if same(u, v):
            remove.append((u, v))
        else:
            union(u, v)
    groups = list(sorted({find(u) for u in range(1, N+1)}))
    added = []
    for u, v in zip(groups[:-1], groups[1:]):
        added.append((u, v))

    if not remove:
        print(0)
    else:
        print(len(remove))
        for i in range(len(remove)):
            print('{} {} {} {}'.format(remove[i][0], remove[i][1], added[i][0], added[i][1]))

N = int(input())
edges = []
for i in range(N-1):
    u, v = map(int, input().split())
    edges.append((u, v))
solve(N, edges)


'''
    Auther: ghoshashis545 Ashis Ghosh
    College: jalpaiguri Govt Enggineering College

'''
from os import path
import sys
from heapq import heappush,heappop
from functools import cmp_to_key as ctk
from collections import deque,defaultdict as dd
from bisect import bisect,bisect_left,bisect_right,insort,insort_left,insort_right
from itertools import permutations
from datetime import datetime
from math import ceil,sqrt,log,gcd
def ii():return int(input())
def si():return input().rstrip()
def mi():return map(int,input().split())
def li():return list(mi())
abc='abcdefghijklmnopqrstuvwxyz'
mod=1000000007
# mod=998244353
inf = float("inf")
vow=['a','e','i','o','u']
dx,dy=[-1,1,0,0],[0,0,1,-1]

def bo(i):
    return ord(i)-ord('a')

file=1

def solve():

    n = ii()

    par = [i for i in range(n+1)]

    freq = [1 for i in range(n+1)]
    def find(i):
        if i==par[i]:
            return i

        par[i] = find(par[i])
        return par[i]

    def union(x,y):
        x = find(x)
        y = find(y)
        if x==y:
            return 0
        if freq[x] < freq[y]:
            par[x] = y
            freq[y] += 1
        else:
            par[y] = x
            freq[x] += 1
        return 1

    erase = []
    for i in range(n-1):

        x,y = mi()

        x1 = find(x)
        y1 = find(y)

        if x1==y1:
            erase.append([x,y])
            continue
        union(x,y)

    add = []

    x = list(set(par[1:]))

    for i in range(1,len(x)):
        if(union(x[0],x[i])):
            add.append([x[0],x[i]])

    print(len(add))
    for i in range(len(add)):
        print(*erase[i],end=" ")
        print(*add[i],end=" ")
        print()

if __name__ =="__main__":

    if(file):

        if path.exists('input.txt'):
            sys.stdin=open('input.txt', 'r')
            sys.stdout=open('output.txt','w')
        else:
            input=sys.stdin.readline
    solve()


lines = sys.stdin.read().split("\n")
lines.pop(-1)
n = int(lines.pop(0))

#Saque esta estructura de internet porque no habia otra
#implementacion nativa en python y no queria calentarme
class Node:
    """Represents an element of a set."""
    def __init__(self, id):
        self.id = id
        self.parent = self
        self.rank = 0
        self.size = 1

    def __repr__(self):
        return 'Node({!r})'.format(self.id)

def Find(x):
    """Returns the representative object of the set containing x."""
    if x.parent is not x:
        x.parent = Find(x.parent)
    return x.parent

def Union(x, y):
    """Combines the sets x and y belong to."""
    xroot = Find(x)
    yroot = Find(y)

    # x and y are already in the same set
    if xroot is yroot:
        return

    # x and y are not in same set, so we merge them
    if xroot.rank < yroot.rank:
        xroot, yroot = yroot, xroot  # swap xroot and yroot

    # merge yroot into xroot
    yroot.parent = xroot
    xroot.size += yroot.size
    if xroot.rank == yroot.rank:
        xroot.rank = xroot.rank + 1

nodos = [Node(i) for i in range(n+1)]
edges = []
final = []
for line in lines:
    a = nodos[int(line.split(" ")[0])]
    b = nodos[int(line.split(" ")[1])]
    if (Find(a) != Find(b)):
        Union(a, b)
    else:
        edges.append( (a,b) )

for i in range(2,n+1):
    if (Find(nodos[1]) != Find(nodos[i])):
        final.append( ( nodos[1],nodos[i] ) )
        Union(nodos[1],nodos[i])

print(len(final))
for i in range(len(final)):
    print(edges[i][0].id, end=" ")
    print(edges[i][1].id, end=" ")
    print(final[i][0].id, end=" ")
    print(final[i][1].id, end=" ")


import sys

lines = sys.stdin.read().split("\n")
lines.pop(-1)
n = int(lines.pop(0))

#Saque esta estructura de internet porque no habia otra
#implementacion nativa en python y no queria calentarme
class Node:
    """Represents an element of a set."""
    def __init__(self, id):
        self.id = id
        self.parent = self
        self.rank = 0
        self.size = 1

    def __repr__(self):
        return 'Node({!r})'.format(self.id)

def Find(x):
    """Returns the representative object of the set containing x."""
    if x.parent is not x:
        x.parent = Find(x.parent)
    return x.parent

def Union(x, y):
    """Combines the sets x and y belong to."""
    xroot = Find(x)
    yroot = Find(y)

    # x and y are already in the same set
    if xroot is yroot:
        return

    # x and y are not in same set, so we merge them
    if xroot.rank < yroot.rank:
        xroot, yroot = yroot, xroot  # swap xroot and yroot

    # merge yroot into xroot
    yroot.parent = xroot
    xroot.size += yroot.size
    if xroot.rank == yroot.rank:
        xroot.rank = xroot.rank + 1

nodos = [Node(i) for i in range(n+1)]
edges = []
final = []
for line in lines:
    a = nodos[int(line.split(" ")[0])]
    b = nodos[int(line.split(" ")[1])]
    if (Find(a) != Find(b)):
        Union(a, b)
    else:
        edges.append( (a,b) )

for i in range(2,n+1):
    if (Find(nodos[1]) != Find(nodos[i])):
        final.append( ( nodos[1],nodos[i] ) )
        Union(nodos[1],nodos[i])

print(len(final))
for i in range(len(final)):
    print(edges[i][0].id, end=" ")
    print(edges[i][1].id, end=" ")
    print(final[i][0].id, end=" ")
    print(final[i][1].id, end=" ")


def find_set(p, a, shorten=True):
    t = a
    while p[t] != t:
        t = p[t]
    if shorten:
        p[a] = t
    return t

def union(p, a, b, acyclic):
    pa = find_set(p, a)
    pb = find_set(p, b)
    if pa != pb:
        if p[b] != b and p[a] == a:
            p[a] = pb
        else:
            p[b] = pa
    elif a != b:
        acyclic.append((a, b))

n = int(input())
p = [0] * (n + 1)
ac = []
for i in range(1, n + 1):
    p[i] = i
for _ in range(n - 1):
    a, b = sorted(map(int, input().split()))
    union(p, a, b, ac)

print(len(ac))
j = 0
for i in range(2, n+1):
    if i == p[i] and p[i] != p[1]:
        print(*ac[j], 1, i)
        j += 1


def find_set(p, a, shorten=True):
    t = a
    while p[t] != t:
        t = p[t]
    if shorten:
        p[a] = t
    return t

def union(p, a, b, acyclic):
    pa = find_set(p, a)
    pb = find_set(p, b)
    if pa != pb:
        p[b] = pa
    elif a != b:
        acyclic.append((a, b))

n = int(input())
p = [0] * (n + 1)
ac = []
for i in range(1, n + 1):
    p[i] = i
for _ in range(n - 1):
    a, b = list(map(int, input().split()))
    union(p, a, b, ac)

print(len(ac))
j = 0
for i in range(2, n+1):
    if i == p[i] and p[i] != 1:
        print(*ac[j], 1, i)
        j += 1


def find_set(p, a, shorten=True):
    t = a
    while p[t] != t:
        t = p[t]
    if shorten:
        p[a] = t
    return t

def union(p, a, b, acyclic):
    pa = find_set(p, a)
    pb = find_set(p, b)
    if pa != pb:
        p[pb] = pa
    elif a != b:
        acyclic.append((a, b))

n = int(input())
p = [0] * (n + 1)
ac = []
for i in range(1, n + 1):
    p[i] = i
for _ in range(n - 1):
    a, b = list(map(int, input().split()))
    union(p, a, b, ac)

print(len(ac))
j = 0
g = find_set(p, 1)
for i in range(2, n+1):
    if find_set(p, i) != g:
        union(p, 1, i, [])
        print(*ac[j], 1, i)
        j += 1


def find_set(p, a, shorten=True):
    t = a
    while p[t] != t:
        t = p[t]
    if shorten:
        p[a] = t
    return t

def union(p, a, b, acyclic):
    pa = find_set(p, a)
    pb = find_set(p, b)
    if pa != pb:
        p[b] = pa
    elif a != b:
        acyclic.append((a, b))

n = int(input())
p = [0] * (n + 1)
ac = []
for i in range(1, n + 1):
    p[i] = i
for _ in range(n - 1):
    a, b = sorted(map(int, input().split()))
    union(p, a, b, ac)

print(len(ac))
j = 0
for i in range(2, n+1):
    if i == p[i] and p[i] != p[1]:
        print(*ac[j], 1, i)
        j += 1


def find_set(p, a, shorten=True):
    t = a
    while p[t] != t:
        t = p[t]
    if shorten:
        p[a] = t
    return t

def union(p, a, b, acyclic):
    pa = find_set(p, a)
    pb = find_set(p, b)
    if pa != pb:
        if p[b] != b and p[a] == a:
            p[a] = b
        else:
            p[b] = pa
    elif a != b:
        acyclic.append((a, b))

n = int(input())
p = [0] * (n + 1)
ac = []
for i in range(1, n + 1):
    p[i] = i
for _ in range(n - 1):
    a, b = sorted(map(int, input().split()))
    union(p, a, b, ac)

print(len(ac))
j = 0
for i in range(2, n+1):
    if i == p[i] and p[i] != p[1]:
        print(*ac[j], 1, i)
        j += 1


def find_set(p, a, shorten=True):
    t = a
    while p[t] != t:
        t = p[t]
    if shorten:
        p[a] = t
    return t

def union(p, a, b, acyclic):
    pa = find_set(p, a)
    pb = find_set(p, b)
    if pa != pb:
        p[pb] = pa
    elif a != b:
        acyclic.append((a, b))

n = int(input())
p = [0] * (n + 1)
ac = []
for i in range(1, n + 1):
    p[i] = i
for _ in range(n - 1):
    a, b = sorted(map(int, input().split()))
    union(p, a, b, ac)

print(len(ac))
j = 0
for i in range(2, n+1):
    if i == p[i] and p[i] != p[1]:
        print(*ac[j], 1, i)
        j += 1


def find_set(p, a, shorten=True):
    t = a
    while p[t] != t:
        t = p[t]
    if shorten:
        p[a] = t
    return t

def union(p, a, b, acyclic):
    pa = find_set(p, a)
    pb = find_set(p, b)
    if pa != pb:
        p[b] = pa
    elif a != b:
        acyclic.append((a, b))

n = int(input())
p = [0] * (n + 1)
ac = []
for i in range(1, n + 1):
    p[i] = i
for _ in range(n - 1):
    a, b = list(map(int, input().split()))
    union(p, a, b, ac)

print(len(ac))
j = 0
for i in range(2, n+1):
    if i == p[i] and p[i] != 1:
        print(1, i, *ac[j])
        j += 1


class Graph:
    def __init__(self,n):
        self.rank=[1]*(n+1)
        self.parent=[0]+[i for i in range(1,n+1)]

    def find(self,a):
        if self.parent[a]==a:
            return a
        if self.parent[a]!=a:
            self.parent[a]=self.find(self.parent[a])
        return self.parent[a]

    def union(self,a,b):
        pa=self.find(a)
        pb=self.find(b)
        if pa!=pb:
            if self.rank[pa]>self.rank[pb]:
                self.parent[pb]=pa
            elif self.rank[pa]<self.rank[pb]:
                self.parent[pa]=pb
            else:
                self.parent[pb]=pa
                self.rank[pa]+=1
            return 1
        else:
            delete.append([a,b])
        return 0
n=int(input())
graph=Graph(n)
c=n
delete=[]
for _ in range(n-1):
    a,b=map(int,input().split())
    c-=graph.union(a,b)
arr=[]
print(c-1)
for i in range(1,n+1):
    arr.append(graph.parent[i])
arr=list(set(arr))
for i in range(1,len(arr)):
    print(delete[i-1][0],delete[i-1][1],arr[0],arr[i])


class Graph:
    def __init__(self,n):
        self.rank=[1]*(n+1)
        self.parent=[0]+[i for i in range(1,n+1)]

    def find(self,a):
        if self.parent[a]==a:
            return a
        if self.parent[a]!=a:
            self.parent[a]=self.find(self.parent[a])
        return self.parent[a]

    def union(self,a,b):
        pa=self.find(a)
        pb=self.find(b)
        if pa!=pb:
            if self.rank[pa]>self.rank[pb]:
                self.parent[pb]=pa
            elif self.rank[pa]<self.rank[pb]:
                self.parent[pa]=pb
            else:
                self.parent[pb]=pa
                self.rank[pa]+=1
            return 1
        else:
            delete.append([a,b])
        return 0
n=int(input())
graph=Graph(n)
c=n
delete=[]
for _ in range(n-1):
    a,b=map(int,input().split())
    c-=graph.union(a,b)
arr=[]
print(c-1)
for i in range(1,n+1):
    arr.append(graph.find(i))
arr=list(set(arr))
for i in range(1,len(arr)):
    print(delete[i-1][0],delete[i-1][1],arr[0],arr[i])


n = int( input() )

p = [0]*n
rank = [0]*n

for i in range( n ):
    p[i] = i

def find_set( x ):

    if x == p[x]:
        return ( x )

    return ( find_set( p[x] ) )

def union_set( a, b ):

    fa = find_set( a )
    fb = find_set( b )

    if rank[fa] < rank[fb]:
        p[fa] = fb
    else:
        p[fb] = fa

    if rank[a] == rank[b]:
        rank[a] += 1

edges = []

for i in range( n-1 ):
    a, b = list( map( int, input().split() ) )

    fa = find_set(a-1)
    fb = find_set(b-1)

    if fa == fb:
        edges.append( (a-1,b-1,fa) )
    else:
        union_set( a-1, b-1 )

#print( edges )

used = [False] * len(edges)
P = []

q = []

for i in range(n):
    if find_set(i) == i:
        q.append(i)

for i in range( len(q)-1 ):
    P.append( (edges[i][0]+1, edges[i][1]+1, q[i]+1, q[i+1]+1) )
    union_set( q[i], q[i+1] )

print( len(P ) )

for i, j, k, z in P:
    print( i, j, k, z )


n = int( input() )

p = [0]*n
rank = [0]*n

for i in range( n ):
    p[i] = i

def find_set( x ):

    if x == p[x]:
        return ( x )

    return ( find_set( p[x] ) )

def union_set( a, b ):

    fa = find_set( a )
    fb = find_set( b )

    if rank[fa] < rank[fb]:
        p[fa] = fb
    else:
        p[fb] = fa

    if rank[a] == rank[b]:
        rank[a] += 1

edges = []

for i in range( n-1 ):
    a, b = list( map( int, input().split() ) )

    fa = find_set(a-1)
    fb = find_set(b-1)

    if fa == fb:
        edges.append( (a-1,b-1,fa) )
    else:
        union_set( a-1, b-1 )

#print( edges )

used = [False] * len(edges)
P = []

idx = 0

for i in range(n):
    if find_set(i) == i:
        for j in range(n):
            if i != j and find_set(j) == j:
                P.append( (edges[idx][0]+1, edges[idx][1]+1, i+1, j+1) )
                idx += 1
                union_set( i, j )
                break

print( len(P ) )

for i, j, k, z in P:
    print( i, j, k, z )


n = int( input() )

p = [0]*n
rank = [0]*n
deg = [0]*n
edges = []

for i in range( n ):
    p[i] = i

def find_set( x ):

    if x == p[x]:
        return ( x )

    return ( find_set( p[x] ) )

def union_set( a, b ):

    fa = find_set( a )
    fb = find_set( b )

    if rank[fa] < rank[fb]:
        p[fa] = fb
    else:
        p[fb] = fa

    if rank[a] == rank[b]:
        rank[a] += 1

adj = [ ]
for i in range(n):
    adj.append([])

memo = {}

for i in range( n-1 ):
    a, b = list( map( int, input().split() ) )
    deg[a-1] += 1
    deg[b-1] += 1
    adj[a-1].append(b-1)
    adj[b-1].append(a-1)
    memo[ (a,b) ] = 1
    memo[ (b,a) ] = 1
    union_set( a-1, b-1 )

visited = [False]*n
group = [0]*n

def dfs( u, c ):

    if visited[u]:
        return

    visited[u] = True
    group[u] = c

    for v in adj[u]:
        if visited[v] == False:
            dfs( v, c )

cnt = 0
for i in range(n):
    if visited[i] == False:
        cnt += 1
        dfs(i, cnt)

#print( group )

P = []

for i in range(n):
    if find_set(i) == i:
        for j in range(n):
            if i != j and find_set(j) == j:

                fl = False
                idx = -1
                for v in adj[i]:
                    if fl == False:
                        fl = True
                        idx = v
                    elif deg[idx] < deg[v]:
                        idx = v

                P.append( (i+1, idx+1, i+1, j+1) )
                union_set( i, j )

print( len(P ) )

for i, j, k, z in P:
    print( i, j, k, z )


n = int( input() )

p = [0]*n
rank = [0]*n
deg = [0]*n
edges = []

for i in range( n ):
    p[i] = i

def find_set( x ):

    if x == p[x]:
        return ( x )

    return ( find_set( p[x] ) )

def union_set( a, b ):

    fa = find_set( a )
    fb = find_set( b )

    if rank[fa] < rank[fb]:
        p[fa] = fb
    else:
        p[fb] = fa

    if rank[a] == rank[b]:
        rank[a] += 1

adj = [ ]
for i in range(n+1):
    adj.append([])

memo = {}

edges = []

for i in range( n-1 ):
    a, b = list( map( int, input().split() ) )

    fa = find_set(a-1)
    fb = find_set(b-1)

    if fa == fb:
        edges.append( (a-1,b-1,fa) )
    else:
        union_set( a-1, b-1 )

#print( edges )

used = [False] * len(edges)
P = []

for i in range(n):
    if find_set(i) == i:
        for j in range(n):
            if i != j and find_set(j) == j:

                idx = -1

                for k in range( len(edges) ):
                    if ( edges[k][2] == i or edges[k][2] == j ) and used[k] == False:
                        idx = k
                        used[k] = True
                        break

                if idx == -1:
                    continue

                P.append( (edges[idx][0]+1, edges[idx][1]+1, i+1, j+1) )
                union_set( i, j )
                break

print( len(P ) )

for i, j, k, z in P:
    print( i, j, k, z )


#import math
#from functools import lru_cache
#import heapq
#from collections import defaultdict
#from collections import Counter
#from sys import stdout
#from sys import setrecursionlimit
from sys import stdin
input = stdin.readline
n = int(input())
parents = list(range(n))
ranks = [0]*n
def find(x):
    if(parents[x] != x):
        parents[x] = find(parents[x])
    return parents[x]
def union(x, y):
    xp = find(x)
    yp = find(y)
    if(ranks[xp]>ranks[yp]): x, y, xp, yp = y, x, yp, xp
    parents[xp] = yp
    if(ranks[xp] == ranks[yp]): ranks[yp] += 1
c = []
for ni in range(n-1):
    s, e = [int(x) for x in input().strip().split()]
    s-=1
    e-=1
    sp = find(s)
    ep = find(e)
    if(sp==ep):
        c.append([s, e])
    else:
        union(s, e)
ntc = list(set(parents))
#print(ntc)
print(len(ntc) - 1)
for i in range(1, len(ntc)):
    print(c[i-1][0]+1, c[i-1][1]+1, ntc[i]+1, ntc[i-1]+1)


#import math
#from functools import lru_cache
#import heapq
#from collections import defaultdict
#from collections import Counter
#from sys import stdout
#from sys import setrecursionlimit
from sys import stdin
input = stdin.readline
n = int(input())
parents = list(range(n))
ranks = [0]*n
def find(x):
    if(parents[x] != x):
        parents[x] = find(parents[x])
    return parents[x]
def union(x, y):
    xp = find(x)
    yp = find(y)
    if(ranks[xp]>ranks[yp]): xp, yp = yp, xp
    parents[xp] = yp
    if(ranks[xp] == ranks[yp]): ranks[yp] += 1
c = []
for ni in range(n-1):
    s, e = [int(x) for x in input().strip().split()]
    s-=1
    e-=1
    sp = find(s)
    ep = find(e)
    if(sp==ep):
        c.append([s, e])
    else:
        union(s, e)
    #print(parents)
#print(parents)
for ni in range(n):
    find(ni)
ntc = list(set(parents))
#print(ntc)
print(len(ntc) - 1)
for i in range(1, len(ntc)):
    print(c[i-1][0]+1, c[i-1][1]+1, ntc[i]+1, ntc[i-1]+1)


#include <bits/stdc++.h>

#define FOR(i, a, n) for(int i = (int)(a); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define all(a) a.begin(),a.end()
#define pb push_back
#define LSOne(S) (S & (-S))
#define dbg(x) cerr << ">>>> " << x << endl;
#define _ << " , " <<
#define mp make_pair
#define mt make_tuple
#define x first
#define y second
#define ii pair<int,int>
#define iii pair<int, ii>
#define lll pair<ll, pair<ll, ll> >
#define maxn 111111
#define PI 3.141592654
#define vi vector<ll>

typedef unsigned long long llu;
typedef long long int ll;
typedef long double ld;

const int INF = 0x3f3f3f3f;
const double EPS = 1e-6;

using namespace std;

string pat;
bool buc[444],has;
int n;

bool test(string cur){
	if(has){
		int i = 0,j = cur.size()-1,k = pat.size()-10;
		while(pat[i] != '*'){
			if(i >= cur.size()) return false;
			if(pat[i] == '?'){
				if(!buc[cur[i]]) return false;
			} else {
				if(pat[i] != cur[i]) return false;
			}
			i++;
		}
		while(pat[k] != '*'){
			if(j < 0) return false;
			if(pat[k] == '?'){
				if(!buc[cur[j]]) return false;
			} else {
				if(pat[k] != cur[j]) return false;
			}
			k--; j--;
		}
		if(j < i) return false;
		for(int z = i; z <= j; z++) if(buc[cur[z]]) return false;
		return true;
	} else {
		if(pat.size() != cur.size()) return false;
		REP(i,pat.size()){
			if(pat[i] == '?'){
				if(!buc[cur[i]]) return false;
			} else {
				if(pat[i] != cur[i]) return false;
			}
		}
		return true;
	}
}

int main(){
	cin >> pat; REP(i,pat.size()) buc[pat[i]] = true;
	cin >> pat;
	cin >> n;
	REP(i,pat.size()) if(pat[i] == '*') has = true;
	while(n--){
		string cur;
		cin >> cur;
		if(test(cur)) puts("YES");
		else puts("NO");
	}
	return 0;
}


#include <bits/stdc++.h>

#define FOR(i, a, n) for(int i = (int)(a); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define all(a) a.begin(),a.end()
#define pb push_back
#define LSOne(S) (S & (-S))
#define dbg(x) cerr << ">>>> " << x << endl;
#define _ << " , " <<
#define mp make_pair
#define mt make_tuple
#define x first
#define y second
#define ii pair<int,int>
#define iii pair<int, ii>
#define lll pair<ll, pair<ll, ll> >
#define maxn 111111
#define PI 3.141592654
#define vi vector<ll>

typedef unsigned long long llu;
typedef long long int ll;
typedef long double ld;

const int INF = 0x3f3f3f3f;
const double EPS = 1e-6;

using namespace std;

int n;
bool buc[400];

int main(){
	string good,pat;
	cin >> good >> pat;
	REP(i,good.size()) buc[good[i]] = true;
	scanf("%d%*c",&n);
	while(n--){
		bool ok = true;
		string cur;
		getline(cin,cur);
		if(cur.size() > pat.size() ||
			(pat.size()-cur.size()) >= 2){
			puts("NO");
			continue;
		}

		REP(i,pat.size()){
			if(pat[i] != '?' && pat[i] != '*'){
				if(buc[pat[i]] == false){
					ok = false;
					break;
				}
			}
		}

		int off = 0;
		REP(i,pat.size()){
			if(pat[i] != '?' && pat[i] != '*'){
				if(cur[i-off] != pat[i]){
					ok = false;
					break;
				}
			} else if(pat[i] == '?'){
				if(!buc[cur[i-off]]){
					ok = false;
					break;
				}
			} else if(pat[i] == '*'){
				if(cur.size() != pat.size()) off++;
				else if(buc[cur[i]] != false){
					ok = false;
					break;
				}
			}
		}
		if(ok) puts("YES");
		else puts("NO");
	}
	return 0;
}


#include <bits/stdc++.h>

#define FOR(i, a, n) for(int i = (int)(a); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define all(a) a.begin(),a.end()
#define pb push_back
#define LSOne(S) (S & (-S))
#define dbg(x) cerr << ">>>> " << x << endl;
#define _ << " , " <<
#define mp make_pair
#define mt make_tuple
#define x first
#define y second
#define ii pair<int,int>
#define iii pair<int, ii>
#define lll pair<ll, pair<ll, ll> >
#define maxn 111111
#define PI 3.141592654
#define vi vector<ll>

typedef unsigned long long llu;
typedef long long int ll;
typedef long double ld;

const int INF = 0x3f3f3f3f;
const double EPS = 1e-6;

using namespace std;

int n;
bool buc[30];

int main(){
	string good,pat;
	cin >> good >> pat;
	REP(i,good.size()) buc[good[i]-'a'] = true;
	scanf("%d%*c",&n);
	while(n--){
		bool ok = true;
		string cur;
		getline(cin,cur);
		if(cur.size() > pat.size() ||
			(pat.size()-cur.size()) >= 2){
			puts("NO");
			continue;
		}

		REP(i,pat.size()){
			if(pat[i] != '?' && pat[i] != '*'){
				if(buc[pat[i]-'a'] == false){
					ok = false;
					break;
				}
			}
		}

		int off = 0;
		REP(i,pat.size()){
			if(pat[i] != '?' && pat[i] != '*'){
				if(cur[i-off] != pat[i]){
					ok = false;
					break;
				}
			} else if(pat[i] == '?'){
				if(!buc[cur[i-off]-'a']){
					ok = false;
					break;
				}
			} else if(pat[i] == '*'){
				if(cur.size() != pat.size()) off++;
			}
		}
		if(ok) puts("YES");
		else puts("NO");
	}
	return 0;
}


#include <bits/stdc++.h>

#define FOR(i, a, n) for(int i = (int)(a); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define all(a) a.begin(),a.end()
#define pb push_back
#define LSOne(S) (S & (-S))
#define dbg(x) cerr << ">>>> " << x << endl;
#define _ << " , " <<
#define mp make_pair
#define mt make_tuple
#define x first
#define y second
#define ii pair<int,int>
#define iii pair<int, ii>
#define lll pair<ll, pair<ll, ll> >
#define maxn 111111
#define PI 3.141592654
#define vi vector<ll>

typedef unsigned long long llu;
typedef long long int ll;
typedef long double ld;

const int INF = 0x3f3f3f3f;
const double EPS = 1e-6;

using namespace std;

bool buc[444];
int n;

int main(){
	string pat;
	cin >> pat; REP(i,pat.size()) buc[pat[i]] = true;
	cin >> pat;
	cin >> n;
	while(n--){
		string cur,ch;
		cin >> cur;
		bool enter = false, out = false, ok = true;
		REP(i,cur.size()){
			if(buc[cur[i]]) {
				ch.pb(cur[i]);
				if(enter) out = true;
			} else if(!out) enter = true;
			else ok = false;
		}
		REP(i,pat.size()){
			if(pat[i] == '*') break;
			if(i == pat.size()-1){
				if(enter){
					ok = false;
				}
			}
		}

		int i = 0, j = 0;
		while(i < pat.size()){
			if(pat[i] != '*'){
				if(pat[i] == '?'){
					if(!buc[ch[j]]) ok = false;
				} else if(pat[i] != ch[j]) ok = false;
				j++;
			}
			i++;
		}

		if(ok && i == pat.size() && j == ch.size()) puts("YES");
		else puts("NO");
	}
	return 0;
}